diff --git a/src/lib.rs b/src/lib.rs index 0a0a094f..b890b067 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -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; diff --git a/src/problem_1982_find_array_given_subset_sums/divide_and_conquer.rs b/src/problem_1982_find_array_given_subset_sums/divide_and_conquer.rs new file mode 100644 index 00000000..bfcadfd5 --- /dev/null +++ b/src/problem_1982_find_array_given_subset_sums/divide_and_conquer.rs @@ -0,0 +1,64 @@ +pub struct Solution; + +// ------------------------------------------------------ snip ------------------------------------------------------ // + +impl Solution { + pub fn recover_array(n: i32, sums: Vec) -> Vec { + 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) -> Vec { + Self::recover_array(n, sums) + } +} + +#[cfg(test)] +mod tests { + #[test] + fn test_solution() { + super::super::tests::run::(); + } +} diff --git a/src/problem_1982_find_array_given_subset_sums/mod.rs b/src/problem_1982_find_array_given_subset_sums/mod.rs new file mode 100644 index 00000000..c15687ea --- /dev/null +++ b/src/problem_1982_find_array_given_subset_sums/mod.rs @@ -0,0 +1,48 @@ +pub mod divide_and_conquer; + +pub trait Solution { + fn recover_array(n: i32, sums: Vec) -> Vec; +} + +#[cfg(test)] +mod tests { + use super::Solution; + use crate::test_utilities; + + pub fn run() { + 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(); + } + } +}