https://leetcode.com/problems/target-sum/
You are given a list of non-negative integers, a1, a2, ..., an, and a target, S. Now you have 2 symbols
+
and-
. For each integer, you should choose one from+
and-
as its new symbol.Find out how many ways to assign symbols to make sum of integers equal to target S.
Example 1:
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.Note:
- The length of the given array is positive and will not exceed 20.
- The sum of elements in the given array will not exceed 1000.
- Your output answer is guaranteed to be fitted in a 32-bit integer.
DFS,直觀但慢
class Solution {
public:
vector<int> remain;
int result = 0;
int findTargetSumWays(vector<int>& nums, int S) {
remain = vector<int>(nums.size(), 0);
remain.back() = nums.back();
for(int i = nums.size()-2; i >= 0; --i){
remain[i] = remain[i+1]+nums[i];
}
dfs(0, 0, S, nums);
return result;
}
void dfs(int pos, int inter, int S, vector<int>& nums){
if(pos == nums.size()){
if(inter == S) ++result;
return;
}else{
if(S > inter+remain[pos] || S < inter-remain[pos]) return;
dfs(pos+1, inter+nums[pos], S, nums);
dfs(pos+1, inter-nums[pos], S, nums);
}
}
};
化爲子集合問題,使用dp求解,快
將正數和負數看成兩個數集
class Solution {
public:
int findTargetSumWays(vector<int>& nums, int S) {
int sum = 0;
for(int n : nums) sum += n;
if(sum < S || (S+sum)%2 != 0) return 0;
int target = (sum+S)/2;
vector<int> dp(target+1, 0);
dp[0] = 1;
for(int n : nums){
for(int i = target; i >= n; --i){
dp[i] += dp[i-n];
}
}
return dp[target];
}
};