-
-
Notifications
You must be signed in to change notification settings - Fork 2.6k
Expand file tree
/
Copy pathsubset_sum.rs
More file actions
81 lines (78 loc) · 2.92 KB
/
subset_sum.rs
File metadata and controls
81 lines (78 loc) · 2.92 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
//! This module provides a solution to the subset sum problem using dynamic programming.
//!
//! # Complexity
//! - Time complexity: O(n * sum) where n is array length and sum is the target sum
//! - Space complexity: O(n * sum) for the DP table
/// Determines if there exists a subset of the given array that sums to the target value.
/// Uses dynamic programming to solve the subset sum problem.
///
/// # Arguments
/// * `arr` - A slice of integers representing the input array.
/// * `required_sum` - The target sum to check for.
///
/// # Returns
/// * `bool` - A boolean indicating whether a subset exists that sums to the target.
pub fn is_sum_subset(arr: &[i32], required_sum: i32) -> bool {
let n = arr.len();
// Handle edge case where required sum is 0 (empty subset always sums to 0)
if required_sum == 0 {
return true;
}
// Handle edge case where array is empty but required sum is positive
if n == 0 && required_sum > 0 {
return false;
}
// dp[i][j] stores whether sum j can be achieved using first i elements
let mut dp = vec![vec![false; required_sum as usize + 1]; n + 1];
// Base case: sum 0 can always be achieved with any number of elements (empty subset)
for i in 0..=n {
dp[i][0] = true;
}
// Base case: with 0 elements, no positive sum can be achieved
for j in 1..=required_sum as usize {
dp[0][j] = false;
}
// Fill the DP table
for i in 1..=n {
for j in 1..=required_sum as usize {
if arr[i - 1] > j as i32 {
// Current element is too large, exclude it
dp[i][j] = dp[i - 1][j];
} else {
// Either exclude the current element or include it
dp[i][j] = dp[i - 1][j] || dp[i - 1][j - arr[i - 1] as usize];
}
}
}
dp[n][required_sum as usize]
}
#[cfg(test)]
mod tests {
use super::*;
// Macro to generate multiple test cases for the is_sum_subset function
macro_rules! subset_sum_tests {
($($name:ident: $input:expr => $expected:expr,)*) => {
$(
#[test]
fn $name() {
let (arr, sum) = $input;
assert_eq!(is_sum_subset(arr, sum), $expected);
}
)*
};
}
subset_sum_tests! {
// Common test cases
test_case_1: (&[2, 4, 6, 8], 5) => false,
test_case_2: (&[2, 4, 6, 8], 14) => true,
test_case_3: (&[3, 34, 4, 12, 5, 2], 9) => true,
test_case_4: (&[3, 34, 4, 12, 5, 2], 30) => false,
test_case_5: (&[1, 2, 3, 4, 5], 15) => true,
// Edge test cases
test_case_empty_array_positive_sum: (&[], 5) => false,
test_case_empty_array_zero_sum: (&[], 0) => true,
test_case_zero_sum: (&[1, 2, 3], 0) => true,
test_case_single_element_match: (&[5], 5) => true,
test_case_single_element_no_match: (&[3], 5) => false,
}
}