Skip to content

Commit d94e821

Browse files
authored
Implement subset sum using backtracking (rust-lang#765)
* feat[backtracking]: implement subset sum * chore(docs): add docstring * chore: format code * chore: change `i32` to `isize` * docs: remove redundant comment
1 parent 46ad2da commit d94e821

File tree

2 files changed

+57
-0
lines changed

2 files changed

+57
-0
lines changed

src/backtracking/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ mod n_queens;
66
mod parentheses_generator;
77
mod permutations;
88
mod rat_in_maze;
9+
mod subset_sum;
910
mod sudoku;
1011

1112
pub use all_combination_of_size_k::generate_all_combinations;
@@ -16,4 +17,5 @@ pub use n_queens::n_queens_solver;
1617
pub use parentheses_generator::generate_parentheses;
1718
pub use permutations::permute;
1819
pub use rat_in_maze::find_path_in_maze;
20+
pub use subset_sum::has_subset_with_sum;
1921
pub use sudoku::sudoku_solver;

src/backtracking/subset_sum.rs

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
//! This module provides functionality to check if there exists a subset of a given set of integers
2+
//! that sums to a target value. The implementation uses a recursive backtracking approach.
3+
4+
/// Checks if there exists a subset of the given set that sums to the target value.
5+
pub fn has_subset_with_sum(set: &[isize], target: isize) -> bool {
6+
backtrack(set, set.len(), target)
7+
}
8+
9+
fn backtrack(set: &[isize], remaining_items: usize, target: isize) -> bool {
10+
// Found a subset with the required sum
11+
if target == 0 {
12+
return true;
13+
}
14+
// No more elements to process
15+
if remaining_items == 0 {
16+
return false;
17+
}
18+
// Check if we can find a subset including or excluding the last element
19+
backtrack(set, remaining_items - 1, target)
20+
|| backtrack(set, remaining_items - 1, target - set[remaining_items - 1])
21+
}
22+
23+
#[cfg(test)]
24+
mod tests {
25+
use super::*;
26+
27+
macro_rules! has_subset_with_sum_tests {
28+
($($name:ident: $test_case:expr,)*) => {
29+
$(
30+
#[test]
31+
fn $name() {
32+
let (set, target, expected) = $test_case;
33+
assert_eq!(has_subset_with_sum(set, target), expected);
34+
}
35+
)*
36+
}
37+
}
38+
39+
has_subset_with_sum_tests! {
40+
test_small_set_with_sum: (&[3, 34, 4, 12, 5, 2], 9, true),
41+
test_small_set_without_sum: (&[3, 34, 4, 12, 5, 2], 30, false),
42+
test_consecutive_set_with_sum: (&[1, 2, 3, 4, 5, 6], 10, true),
43+
test_consecutive_set_without_sum: (&[1, 2, 3, 4, 5, 6], 22, false),
44+
test_large_set_with_sum: (&[5, 10, 12, 13, 15, 18, -1, 10, 50, -2, 3, 4], 30, true),
45+
test_empty_set: (&[], 0, true),
46+
test_empty_set_with_nonzero_sum: (&[], 10, false),
47+
test_single_element_equal_to_sum: (&[10], 10, true),
48+
test_single_element_not_equal_to_sum: (&[5], 10, false),
49+
test_negative_set_with_sum: (&[-7, -3, -2, 5, 8], 0, true),
50+
test_negative_sum: (&[1, 2, 3, 4, 5], -1, false),
51+
test_negative_sum_with_negatives: (&[-7, -3, -2, 5, 8], -4, true),
52+
test_negative_sum_with_negatives_no_solution: (&[-7, -3, -2, 5, 8], -14, false),
53+
test_even_inputs_odd_target: (&[2, 4, 6, 2, 8, -2, 10, 12, -24, 8, 12, 18], 3, false),
54+
}
55+
}

0 commit comments

Comments
 (0)