Skip to content

Commit

Permalink
Add problem 1755: Closest Subsequence Sum
Browse files Browse the repository at this point in the history
  • Loading branch information
EFanZh committed Jan 15, 2024
1 parent ecb86cb commit c82ef1f
Show file tree
Hide file tree
Showing 3 changed files with 107 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 @@ -1310,6 +1310,7 @@ pub mod problem_1751_maximum_number_of_events_that_can_be_attended_ii;
pub mod problem_1752_check_if_array_is_sorted_and_rotated;
pub mod problem_1753_maximum_score_from_removing_stones;
pub mod problem_1754_largest_merge_of_two_strings;
pub mod problem_1755_closest_subsequence_sum;
pub mod problem_1758_minimum_changes_to_make_alternating_binary_string;
pub mod problem_1759_count_number_of_homogenous_substrings;
pub mod problem_1760_minimum_limit_of_balls_in_a_bag;
Expand Down
62 changes: 62 additions & 0 deletions src/problem_1755_closest_subsequence_sum/binary_search.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
pub struct Solution;

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

use std::slice::Iter;

impl Solution {
fn get_sums_helper(result: &mut Vec<i32>, mut sum: i32, mut iter: Iter<i32>) {
while let Some(next) = iter.next() {
Self::get_sums_helper(result, sum, iter.clone());

sum += next;
}

result.push(sum);
}

fn get_sums(nums: &[i32]) -> Box<[i32]> {
let mut result = Vec::with_capacity(1 << nums.len());

Self::get_sums_helper(&mut result, 0, nums.iter());

result.into_boxed_slice()
}

pub fn min_abs_difference(nums: Vec<i32>, goal: i32) -> i32 {
let (left, right) = nums.split_at(nums.len() / 2);
let left_sums = Self::get_sums(left);
let mut right_sums = Self::get_sums(right);

right_sums.sort_unstable();

let mut result = u32::MAX;

for left_sum in &*left_sums {
let target = goal - left_sum;
let split = right_sums.partition_point(|&x| x < target);
let diff_1 = right_sums.get(split.wrapping_sub(1)).map_or(-1, |&x| target - x);
let diff_2 = right_sums.get(split).map_or(-1, |&x| x - target);

result = result.min(u32::min(diff_1 as _, diff_2 as _));
}

result as _
}
}

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

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

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

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

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

pub fn run<S: Solution>() {
let test_cases = [
((&[5, -7, 3, 5] as &[_], 6), 0),
((&[7, -9, 15, -2], -5), 1),
((&[1, 2, 3], -7), 7),
(
(
&[
-7_074_297, 3_076_735, -5_846_354, 5_008_659, -126_683, 7_039_557, 6_708_811, 3_189_666,
-6_102_417, 6_078_975, -6_448_946, -4_995_910, 2_964_239, -3_248_847, -4_392_269, 7_473_223,
-1_356_059, 3_978_911, 8_009_187, -316_441, 6_524_770, 8_280_309, -2_798_383, 1_310_839,
6_306_594, -6_548_611, -9_712_711, 1_639_314,
],
493_409_180,
),
415_819_391,
),
(
(
&[
-2_224_858, -2_089_988, -482_571, 5_521_468, 8_354_928, 9_459_313, 3_072_588, -2_889_581,
5_156_433,
],
10_530_484,
),
26_240,
),
];

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

0 comments on commit c82ef1f

Please sign in to comment.