Skip to content

Commit a6a9d8e

Browse files
feat: add Subset Sum (TheAlgorithms#2020)
* Create subset_sum.cpp * Update subset_sum.cpp Lint formatting. * chore: apply suggestions from code review * chore: apply suggestions from code review * fix: CI issues Co-authored-by: David Leal <halfpacho@gmail.com>
1 parent f093837 commit a6a9d8e

File tree

1 file changed

+125
-0
lines changed

1 file changed

+125
-0
lines changed

dynamic_programming/subset_sum.cpp

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
/**
2+
* @file
3+
* @brief Implements [Sub-set sum problem]
4+
* (https://en.wikipedia.org/wiki/Subset_sum_problem) algorithm, which tells
5+
* whether a subset with target sum exists or not.
6+
*
7+
* @details
8+
* In this problem, we use dynamic programming to find if we can pull out a
9+
* subset from an array whose sum is equal to a given target sum. The overall
10+
* time complexity of the problem is O(n * targetSum) where n is the size of
11+
* the array. For example, array = [1, -10, 2, 31, -6], targetSum = -14.
12+
* Output: true => We can pick subset [-10, 2, -6] with sum as
13+
* (-10) + 2 + (-6) = -14.
14+
* @author [KillerAV](https://github.com/KillerAV)
15+
*/
16+
17+
#include <cassert> /// for std::assert
18+
#include <iostream> /// for IO operations
19+
#include <vector> /// for std::vector
20+
#include <unordered_map> /// for unordered map
21+
22+
/**
23+
* @namespace dynamic_programming
24+
* @brief Dynamic Programming algorithms
25+
*/
26+
namespace dynamic_programming {
27+
28+
/**
29+
* @namespace subset_sum
30+
* @brief Functions for [Sub-set sum problem]
31+
* (https://en.wikipedia.org/wiki/Subset_sum_problem) algorithm
32+
*/
33+
namespace subset_sum {
34+
35+
/**
36+
* Recursive function using dynamic programming to find if the required sum
37+
* subset exists or not.
38+
* @param arr input array
39+
* @param targetSum the target sum of the subset
40+
* @param dp the map storing the results
41+
* @returns true/false based on if the target sum subset exists or not.
42+
*/
43+
bool subset_sum_recursion(
44+
const std::vector<int> &arr,
45+
int targetSum,
46+
std::vector<std::unordered_map<int, bool>> *dp,
47+
int index = 0) {
48+
49+
if(targetSum == 0) { // Found a valid subset with required sum.
50+
return true;
51+
}
52+
if(index == arr.size()) { // End of array
53+
return false;
54+
}
55+
56+
if ((*dp)[index].count(targetSum)) { // Answer already present in map
57+
return (*dp)[index][targetSum];
58+
}
59+
60+
bool ans = subset_sum_recursion(arr, targetSum - arr[index], dp, index + 1)
61+
|| subset_sum_recursion(arr, targetSum, dp, index + 1);
62+
(*dp)[index][targetSum] = ans; // Save ans in dp map.
63+
return ans;
64+
}
65+
66+
/**
67+
* Function implementing subset sum algorithm using top-down approach
68+
* @param arr input array
69+
* @param targetSum the target sum of the subset
70+
* @returns true/false based on if the target sum subset exists or not.
71+
*/
72+
bool subset_sum_problem(const std::vector<int> &arr, const int targetSum) {
73+
size_t n = arr.size();
74+
std::vector<std::unordered_map<int, bool>> dp(n);
75+
return subset_sum_recursion(arr, targetSum, &dp);
76+
}
77+
} // namespace subset_sum
78+
} // namespace dynamic_programming
79+
80+
/**
81+
* @brief Test Function
82+
* @return void
83+
*/
84+
static void test() {
85+
// custom input vector
86+
std::vector<std::vector<int>> custom_input_arr(3);
87+
custom_input_arr[0] = std::vector<int> {1, -10, 2, 31, -6};
88+
custom_input_arr[1] = std::vector<int> {2, 3, 4};
89+
custom_input_arr[2] = std::vector<int> {0, 1, 0, 1, 0};
90+
91+
std::vector<int> custom_input_target_sum(3);
92+
custom_input_target_sum[0] = -14;
93+
custom_input_target_sum[1] = 10;
94+
custom_input_target_sum[2] = 2;
95+
96+
// calculated output vector by pal_part Function
97+
std::vector<int> calculated_output(3);
98+
99+
for (int i = 0; i < 3; i++) {
100+
calculated_output[i] =
101+
dynamic_programming::subset_sum::subset_sum_problem(
102+
custom_input_arr[i], custom_input_target_sum[i]);
103+
}
104+
105+
// expected output vector
106+
std::vector<bool> expected_output{true, false, true};
107+
108+
// Testing implementation via assert function
109+
// It will throw error if any of the expected test fails
110+
// Else it will give nothing
111+
for (int i = 0; i < 3; i++) {
112+
assert(expected_output[i] == calculated_output[i]);
113+
}
114+
115+
std::cout << "All tests passed successfully!\n";
116+
}
117+
118+
/**
119+
* @brief Main function
120+
* @returns 0 on exit
121+
*/
122+
int main() {
123+
test(); // execute the test
124+
return 0;
125+
}

0 commit comments

Comments
 (0)