494. Target Sum
https://leetcode.com/problems/target-sum/description/
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.
Thoughts
整数数组中选一部分取负,其它不变,问一共有多少种取法能让最后的和等于S。把集合的数看成两个子集,满足sum(P) - sum(!P) = target 和sum(P) + sum(!P) = sum => sum(P) = (sum + target)/2,也就是找和为(sum+target)/2的子集数目,01背包。
Code
/*
* @lc app=leetcode id=494 lang=cpp
*
* [494] Target Sum
*/
// @lc code=start
class Solution {
public:
int findTargetSumWays(vector<int>& nums, int S) {
const int N = nums.size(), sum = accumulate(nums.begin(), nums.end(), 0);
if (sum < S || (sum + S) % 2 != 0) return 0;
const int V = (sum + S) / 2;
vector<int> dp(V + 1, 0);
for (int i = 0; i <= N; ++i) dp[0] = 1;
for (int i = 1; i <= N; ++i) {
for (int j = V; j >= 0; --j) {
dp[j] += (j >= nums[i - 1]) ? dp[j - nums[i - 1]] : 0;
}
}
return dp[V];
}
};
// @lc code=end
class Solution {
public int findTargetSumWays(int[] nums, int target) {
int sum = 0;
for (int num : nums) {
sum += num;
}
if (sum < target || (target + sum) % 2 == 1) {
return 0;
}
int V = (target + sum) / 2;
int[] f = new int[V + 1];
f[0] = 1;
for (int num : nums) {
for (int j = V; j >= num; j--) {
f[j] += f[j - num];
}
}
return f[V];
}
}
Last updated
Was this helpful?