/** * @file * @brief Implements [Sub-set sum problem] * (https://en.wikipedia.org/wiki/Subset_sum_problem) algorithm, which tells * whether a subset with target sum exists or not. * * @details * In this problem, we use dynamic programming to find if we can pull out a * subset from an array whose sum is equal to a given target sum. The overall * time complexity of the problem is O(n * targetSum) where n is the size of * the array. For example, array = [1, -10, 2, 31, -6], targetSum = -14. * Output: true => We can pick subset [-10, 2, -6] with sum as * (-10) + 2 + (-6) = -14. * @author [KillerAV](https://github.com/KillerAV) */ #include /// for std::assert #include /// for IO operations #include /// for unordered map #include /// for std::vector /** * @namespace dynamic_programming * @brief Dynamic Programming algorithms */ namespace dynamic_programming { /** * @namespace subset_sum * @brief Functions for [Sub-set sum problem] * (https://en.wikipedia.org/wiki/Subset_sum_problem) algorithm */ namespace subset_sum { /** * Recursive function using dynamic programming to find if the required sum * subset exists or not. * @param arr input array * @param targetSum the target sum of the subset * @param dp the map storing the results * @returns true/false based on if the target sum subset exists or not. */ bool subset_sum_recursion(const std::vector &arr, int targetSum, std::vector> *dp, int index = 0) { if (targetSum == 0) { // Found a valid subset with required sum. return true; } if (index == arr.size()) { // End of array return false; } if ((*dp)[index].count(targetSum)) { // Answer already present in map return (*dp)[index][targetSum]; } bool ans = subset_sum_recursion(arr, targetSum - arr[index], dp, index + 1) || subset_sum_recursion(arr, targetSum, dp, index + 1); (*dp)[index][targetSum] = ans; // Save ans in dp map. return ans; } /** * Function implementing subset sum algorithm using top-down approach * @param arr input array * @param targetSum the target sum of the subset * @returns true/false based on if the target sum subset exists or not. */ bool subset_sum_problem(const std::vector &arr, const int targetSum) { size_t n = arr.size(); std::vector> dp(n); return subset_sum_recursion(arr, targetSum, &dp); } } // namespace subset_sum } // namespace dynamic_programming /** * @brief Test Function * @return void */ static void test() { // custom input vector std::vector> custom_input_arr(3); custom_input_arr[0] = std::vector{1, -10, 2, 31, -6}; custom_input_arr[1] = std::vector{2, 3, 4}; custom_input_arr[2] = std::vector{0, 1, 0, 1, 0}; std::vector custom_input_target_sum(3); custom_input_target_sum[0] = -14; custom_input_target_sum[1] = 10; custom_input_target_sum[2] = 2; // calculated output vector by pal_part Function std::vector calculated_output(3); for (int i = 0; i < 3; i++) { calculated_output[i] = dynamic_programming::subset_sum::subset_sum_problem( custom_input_arr[i], custom_input_target_sum[i]); } // expected output vector std::vector expected_output{true, false, true}; // Testing implementation via assert function // It will throw error if any of the expected test fails // Else it will give nothing for (int i = 0; i < 3; i++) { assert(expected_output[i] == calculated_output[i]); } std::cout << "All tests passed successfully!\n"; } /** * @brief Main function * @returns 0 on exit */ int main() { test(); // execute the test return 0; }