mirror of
https://github.com/TheAlgorithms/C-Plus-Plus.git
synced 2026-02-03 10:35:34 +08:00
* chore: add cache and build comment to git ignore
* fix: add cmakelists to dynamic programming
* fix: add cmakelists to greedy_algorithms
* fix: add cmakelists to operations_on_datastructures
* fix: add cmakelists to range_queries
* fix: add `dynamic_programmin`, `greedy_algorithms`, `range_queries` and `operations_on_datastructures` subdirectories to cmakelists.txt
* fix: init of transform_reduce in dynamic_programming
* fix: add an include for functional in catalan_numbers
* chore: bump CXX standard to 20
* revert: bump CXX standard to 20
* chore: bump c++ version to 17 and add justification
Arm supports c++ 17
Esp32 supports c++ 23
decision was made to be 17 because it seemed to offer the best combatability
* fix: compilation error in catalan numbers
* fix: add <set> header to longest increasing subsequence nlogn
* fix: add cmath & algorithm header to mo.cpp
* fix: remove register key word from fast integer
* fix: replace using namespace std with std::cin and std::cout
* docs: typo in c++17
* fix: memory leak in bellman_ford
* fix: typo in bellman_ford
* fix: typo in word_break
* fix: dynamic array in coin_change
* fix dynamic array in egg_dropping puzzle
* chore: remove unnecessary comment
* fix: add vla to be an error
* chore: add extra warnings
* fix: use add_compile options instead of set()
* fix: compile options are not strings
* fix: vla in floyd_warshall
* fix: vla in egg_dropping_puzzel
* fix: vla in coin_change
* fix: vla in edit_distance
* fix: vla in floyd_warshall
* feat: remove kadane and replace it with kadane2
* fix: vla in longest_common_subsequence
* fix: int overflow in floyd_warshall
* fix: vla in lisnlogn
* fix: use const vector& instead of array
* fix: use dynamic array instead of vla in knapsack
* fix: use of and in msvc is unsupported by default adding permissive flag fixes it
* test: make executables the tests themselves
* Revert "test: make executables the tests themselves"
This reverts commit 7a16c31c4e.
* fix: make dist constant in print
* fix: namespace issue in unbounded_0_1
* fix: include cstdint to fix compilation
124 lines
3.8 KiB
C++
124 lines
3.8 KiB
C++
/**
|
|
* @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 <cassert> /// for std::assert
|
|
#include <iostream> /// for IO operations
|
|
#include <unordered_map> /// for unordered map
|
|
#include <vector> /// 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<int> &arr, int targetSum,
|
|
std::vector<std::unordered_map<int, bool>> *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<int> &arr, const int targetSum) {
|
|
size_t n = arr.size();
|
|
std::vector<std::unordered_map<int, bool>> 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<std::vector<int>> custom_input_arr(3);
|
|
custom_input_arr[0] = std::vector<int>{1, -10, 2, 31, -6};
|
|
custom_input_arr[1] = std::vector<int>{2, 3, 4};
|
|
custom_input_arr[2] = std::vector<int>{0, 1, 0, 1, 0};
|
|
|
|
std::vector<int> 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<int> 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<bool> 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;
|
|
}
|