494. Target Sum
Input: nums is [1, 1, 1, 1, 1], S is 3.
Output: 5
Explanation:
-1+1+1+1+1 = 3
+1-1+1+1+1 = 3
+1+1-1+1+1 = 3
+1+1+1-1+1 = 3
+1+1+1+1-1 = 3
There are 5 ways to assign symbols to make the sum of nums be target 3.Last updated
Input: nums is [1, 1, 1, 1, 1], S is 3.
Output: 5
Explanation:
-1+1+1+1+1 = 3
+1-1+1+1+1 = 3
+1+1-1+1+1 = 3
+1+1+1-1+1 = 3
+1+1+1+1-1 = 3
There are 5 ways to assign symbols to make the sum of nums be target 3.Last updated
// Top-Down DP with Memoization
int helper(const vector<int>& nums, int i, int sum, int S, unordered_map<string, int>& memo) {
string keyStr = to_string(i) + "_" + to_string(sum);
if (memo.count(keyStr)) return memo[keyStr];
if (i == nums.size()) {
return sum == S ? 1 : 0;
}
int num = nums[i];
int add = helper(nums, i + 1, sum + num, S, memo);
int minus = helper(nums, i + 1, sum - num, S, memo);
int res = add + minus;
return memo[keyStr] = res;
}
int findTargetSumWays(vector<int>& nums, int S) {
unordered_map<string, int> memo;
return helper(nums, 0, 0, S, memo);
}// Bottom-Up 2-D DP
int subsetSum(const vector<int>& nums, int target) {
int n = nums.size();
vector<vector<int> > dp(n + 1, vector<int> (target + 1, 0));
dp[0][0] = 1;
for (int i = 1; i <= n; ++i) {
for (int j = 0; j <= target; ++j) {
if (j >= nums[i - 1]) {
dp[i][j] = dp[i - 1][j] + dp[i - 1][j - nums[i - 1]];
} else {
dp[i][j] = dp[i - 1][j];
}
}
}
return dp.back().back();
}
int findTargetSumWays(vector<int>& nums, int S) { // time: O(n * S); space: O(n * S)
int sum = accumulate(nums.begin(), nums.end(), 0);
return (sum < S || (sum + S) & 0x1) ? 0 : subsetSum(nums, (sum + S) >> 1);
}// Bottom-Up 1-D DP
int subsetSum(const vector<int>& nums, int target) {
int n = nums.size();
vector<int> dp(target + 1, 0);
dp[0] = 1;
for (int i = 0; i < nums.size(); ++i) {
for (int j = target; j >= nums[i]; --j) {
dp[j] += dp[j - nums[i]];
}
}
return dp.back();
}
int findTargetSumWays(vector<int>& nums, int S) { // time: O(n * S); space: O(S)
int sum = accumulate(nums.begin(), nums.end(), 0);
return (sum < S || (sum + S) & 0x1) ? 0 : subsetSum(nums, (sum + S) >> 1);
}// Dynamic Programming
int findTargetSumWays(vector<int>& nums, int S) { // time: O(n * S); space: O(n * S)
int sum = accumulate(nums.begin(), nums.end(), 0);
if (S > sum || S < -sum) return 0;
int n = nums.size(), leftBound = 0, rightBound = 2 * sum;
vector<vector<int> > dp(n + 1, vector<int> (2 * sum + 1, 0));
dp[0][sum] = 1; // -sum ~ sum => 0 ~ 2*sum
for (int i = 1; i <= n; ++i) {
for (int j = leftBound; j <= rightBound; ++j) {
if (j + nums[i - 1] <= rightBound)
dp[i][j] += dp[i - 1][j + nums[i - 1]];
if (j - nums[i - 1] >= leftBound)
dp[i][j] += dp[i - 1][j - nums[i - 1]];
}
}
return dp[n][sum + S];
}// Space Optimized 1-D Dynamic Programming
int findTargetSumWays(vector<int>& nums, int S) { // time: O(n * S); space: O(S)
int sum = accumulate(nums.begin(), nums.end(), 0);
if (S > sum || S < -sum) return 0;
int n = nums.size();
vector<int> dp(2 * sum + 1, 0);
dp[sum] = 1; // -sum ~ sum => 0 ~ 2*sum
for (int i = 0; i < n; ++i) {
vector<int> tmp(2 * sum + 1, 0);
for (int j = 0; j <= 2 * sum; ++j) {
if (dp[j] != 0) {
tmp[j + nums[i]] += dp[j];
tmp[j - nums[i]] += dp[j];
}
}
dp = tmp;
}
return dp[sum + S];
}