Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions DIRECTORY.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@
* [Rod Cutting](https://github.com/TheAlgorithms/Rust/blob/master/src/dynamic_programming/rod_cutting.rs)
* [Snail](https://github.com/TheAlgorithms/Rust/blob/master/src/dynamic_programming/snail.rs)
* [Subset Generation](https://github.com/TheAlgorithms/Rust/blob/master/src/dynamic_programming/subset_generation.rs)
* [Subset Sum](https://github.com/TheAlgorithms/Rust/blob/master/src/dynamic_programming/subset_sum.rs)
* [Trapped Rainwater](https://github.com/TheAlgorithms/Rust/blob/master/src/dynamic_programming/trapped_rainwater.rs)
* [Word Break](https://github.com/TheAlgorithms/Rust/blob/master/src/dynamic_programming/word_break.rs)
* Financial
Expand Down
2 changes: 2 additions & 0 deletions src/dynamic_programming/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ mod optimal_bst;
mod rod_cutting;
mod snail;
mod subset_generation;
mod subset_sum;
mod trapped_rainwater;
mod word_break;

Expand Down Expand Up @@ -45,5 +46,6 @@ pub use self::optimal_bst::optimal_search_tree;
pub use self::rod_cutting::rod_cut;
pub use self::snail::snail;
pub use self::subset_generation::list_subset;
pub use self::subset_sum::is_sum_subset;
pub use self::trapped_rainwater::trapped_rainwater;
pub use self::word_break::word_break;
81 changes: 81 additions & 0 deletions src/dynamic_programming/subset_sum.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,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,
}
}