Skip to content

Commit

Permalink
Add problem 2035: Partition Array Into Two Arrays to Minimize Sum Dif…
Browse files Browse the repository at this point in the history
…ference
  • Loading branch information
EFanZh committed Sep 19, 2024
1 parent 56faf10 commit 2fe533b
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1516,6 +1516,7 @@ pub mod problem_2030_smallest_k_length_subsequence_with_occurrences_of_a_letter;
pub mod problem_2032_two_out_of_three;
pub mod problem_2033_minimum_operations_to_make_a_uni_value_grid;
pub mod problem_2034_stock_price_fluctuation;
pub mod problem_2035_partition_array_into_two_arrays_to_minimize_sum_difference;
pub mod problem_2037_minimum_number_of_moves_to_seat_everyone;
pub mod problem_2038_remove_colored_pieces_if_both_neighbors_are_the_same_color;
pub mod problem_2039_the_time_when_the_network_becomes_idle;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
pub struct Solution;

// ------------------------------------------------------ snip ------------------------------------------------------ //

impl Solution {
fn get_sums(nums: &[i32], sums: &mut [i32]) -> Box<[Vec<i32>]> {
let n = nums.len();
let mut result = vec![Vec::new(); n + 1].into_boxed_slice();

result[0].push(0);

for selected in 1..sums.len() {
let sum = sums[selected & (selected - 1)] + nums[selected.trailing_zeros() as usize];

sums[selected] = sum;
result[selected.count_ones() as usize].push(sum);
}

result
}

pub fn minimum_difference(nums: Vec<i32>) -> i32 {
let (left, right) = nums.split_at(nums.len() / 2);
let mut sums = vec![0; 1 << left.len()].into_boxed_slice();
let mut left_sums = Self::get_sums(left, &mut sums);
let mut right_sums = Self::get_sums(right, &mut sums);
let get_last = |sums: &[Vec<i32>]| *sums.last().and_then(|sums| sums.first()).unwrap();
let sum = get_last(&left_sums) + get_last(&right_sums);
let half = sum.div_euclid(2);
let mut min_sum = u32::MAX;

for (left_sums, right_sums) in left_sums.iter_mut().rev().zip(&mut *right_sums) {
right_sums.sort_unstable();

for &left_sum in &*left_sums {
let target = half - left_sum;
let i = right_sums.partition_point(|&x| x < target);

if let Some(&right_sum) = right_sums.get(i) {
min_sum = u32::min(min_sum, ((left_sum + right_sum) * 2 - sum) as _);
}
}
}

min_sum as _
}
}

// ------------------------------------------------------ snip ------------------------------------------------------ //

impl super::Solution for Solution {
fn minimum_difference(nums: Vec<i32>) -> i32 {
Self::minimum_difference(nums)
}
}

#[cfg(test)]
mod tests {
#[test]
fn test_solution() {
super::super::tests::run::<super::Solution>();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
pub mod meet_in_the_middle;

pub trait Solution {
fn minimum_difference(nums: Vec<i32>) -> i32;
}

#[cfg(test)]
mod tests {
use super::Solution;

pub fn run<S: Solution>() {
let test_cases = [
(&[3, 9, 7, 3] as &[_], 2),
(&[-36, 36], 72),
(&[2, -1, 0, 4, -2, -9], 0),
];

for (nums, expected) in test_cases {
assert_eq!(S::minimum_difference(nums.to_vec()), expected);
}
}
}

0 comments on commit 2fe533b

Please sign in to comment.