Skip to content

Commit

Permalink
Add problem 1982: Find Array Given Subset Sums
Browse files Browse the repository at this point in the history
  • Loading branch information
EFanZh committed Sep 15, 2024
1 parent bc7f6d2 commit f599830
Show file tree
Hide file tree
Showing 3 changed files with 113 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 @@ -1476,6 +1476,7 @@ pub mod problem_1977_number_of_ways_to_separate_numbers;
pub mod problem_1979_find_greatest_common_divisor_of_array;
pub mod problem_1980_find_unique_binary_string;
pub mod problem_1981_minimize_the_difference_between_target_and_chosen_elements;
pub mod problem_1982_find_array_given_subset_sums;
pub mod problem_1984_minimum_difference_between_highest_and_lowest_of_k_scores;
pub mod problem_1985_find_the_kth_largest_integer_in_the_array;
pub mod problem_1986_minimum_number_of_work_sessions_to_finish_the_tasks;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
pub struct Solution;

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

impl Solution {
pub fn recover_array(n: i32, sums: Vec<i32>) -> Vec<i32> {
let n = n as u8;
let mut sums = sums;

sums.sort_unstable();

let mut zero = 0;

(0..n)
.map(|_| {
let [min_1, min_2]: [_; 2] = sums[..2].try_into().ok().unwrap();
let mut diff = min_2 - min_1;

// +---------------+-------------------+---------+-----------+
// | fully matched | partially matched | checked | unchecked |
// +---------------+-------------------+---------+-----------+

let half = sums.len() / 2;
let mut fully_matched = 1;
let mut i = 2;

for all_matched in 1..half {
while fully_matched < all_matched && sums[i] - sums[fully_matched] == diff {
fully_matched += 1;
i += 1;
}

sums[all_matched] = sums[i];
i += 1;
}

sums.truncate(half);

if sums.binary_search(&zero).is_err() {
zero -= diff;
diff = -diff;
}

diff
})
.collect()
}
}

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

impl super::Solution for Solution {
fn recover_array(n: i32, sums: Vec<i32>) -> Vec<i32> {
Self::recover_array(n, sums)
}
}

#[cfg(test)]
mod tests {
#[test]
fn test_solution() {
super::super::tests::run::<super::Solution>();
}
}
48 changes: 48 additions & 0 deletions src/problem_1982_find_array_given_subset_sums/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
pub mod divide_and_conquer;

pub trait Solution {
fn recover_array(n: i32, sums: Vec<i32>) -> Vec<i32>;
}

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

pub fn run<S: Solution>() {
let test_cases = [
(3, &[-3, -2, -1, 0, 0, 1, 2, 3] as &[_]),
(2, &[0, 0, 0, 0]),
(4, &[0, 0, 5, 5, 4, -1, 4, 9, 9, -1, 4, 3, 4, 8, 3, 8]),
(
4,
&[
305, -76, -381, 0, -457, -183, -762, -381, 503, 198, 884, 579, 198, 122, -76, 503,
],
),
];

let mut buffer = Vec::new();

for (n, sums) in test_cases {
let result = S::recover_array(n, sums.to_vec());

buffer.push(0);

for value in result {
for i in 0..buffer.len() {
let new_value = buffer[i] + value;

buffer.push(new_value);
}
}

assert_eq!(
test_utilities::unstable_sorted(buffer.iter().copied()),
test_utilities::unstable_sorted(sums.iter().copied()),
);

buffer.clear();
}
}
}

0 comments on commit f599830

Please sign in to comment.