Leetcode编程题解:494. Target Sum
来源:互联网 发布:怎样关闭136端口 xp 编辑:程序博客网 时间:2024/06/01 10:14
题目:
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: 5Explanation: -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 = 3There are 5 ways to assign symbols to make the sum of nums be target 3.
注意事项:
- 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: int findTargetSumWays(vector<int>& nums, int S) { if(nums.size() == 0) return 0; dfs(nums, S, 0, 0); return cnt; } void dfs(vector<int>& nums, int S, int k, int sum) { if(k == nums.size()) { if(S == sum) cnt++; return; } dfs(nums, S, k + 1, sum + nums[k]); dfs(nums, S, k + 1, sum - nums[k]); }private: int cnt = 0;};
方法二:动态规划、
其实,每个数之前添加+或者-,就相当于这个数是选正数还是负数,就一01背包。
状态表示:
转移方程:
const int maxn = 25;const int maxm = 5005;#define ofs 2003int d[maxn][maxm];class Solution {public: int findTargetSumWays(vector<int>& nums, int S) { if (S > 1000) return 0; bool flag = !(nums[0]); memset(d, 0, sizeof(d)); d[0][nums[0] + ofs] = d[0][-nums[0] + ofs] = 1; for (int i = 1; i < nums.size(); i++) { for (int j = -1000; j <= S + 1000; j++) { d[i][j + ofs] = d[i - 1][j - nums[i] + ofs] + d[i - 1][j + nums[i] + ofs]; } } return flag == true ? d[nums.size() - 1][S + ofs] * 2 : d[nums.size() - 1][S + ofs]; }};
在Solution里面看到一个很好的算法。
转化问题
我们是在一些数前面添加+,一些数前面添加-。我们把添加+的数记为集合P,添加-的数记为集合N。
比如{1, 2, 3, 4, 5}, target = 3。如果我们这么添加:+1 - 2 + 3 - 4 + 5 = 3。则P = {1, 3, 5}, N = {2, 4}。
那么,我们可以得到如下公式:
所以,我们的问题就转化成了:在nums[]
找一个子集P,使P的和为
求子集
那么现在问题可以这么描述:我们有一个数组nums,我们需要求解能够组合集合P的方案数,使P的和为
就0 - 1背包
状态表示:
转移就分为第i个数是否加入我们的集合P。 d[i][j]=d[i−1][j−ai]+d[i−1][j+ai]
转移方程:d[i][j]=d[i−1][j−ai]+d[i−1][j+ai]
d[i,j]=d[i−1,j]+d[i−1,j−aid[i,j]=d[i−1,j]+d[i−1,j−aid[i,j]=d[i−1,j]+d[i−1,j−aid[i,j]=d[i−1,j]+d[i−1,j−aid[i][j]=d[i−1][j−ai]+d[i−1][j+ai]d[i][j]=d[i−1][j−ai]+d[i−1][j+ai]d[i][j]=d[i−1][j−ai]+d[i−1][j+ai]d[i][j]=d[i−1][j−ai]+d[i−1][j+ai]d[i][j]=d[i−1][j−ai]+d[i−1][j+ai]d[i][j]=d[i−1][j−ai]+d[i−1][j+ai]d[i][j]=d[i−1][j−ai]+d[i−1][j+ai]d[i][j]=d[i−1][j−ai]+d[i−1][j+ai]d[i][j]=d[i−1][j−ai]+d[i−1][j+ai]d[i][j]=d[i−1][j−ai]+d[i−1][j+ai]d[i][j]=d[i−1][j−ai]+d[i−1][j+ai]d[i][j]=d[i−1][j−ai]+d[i−1][j+ai]d[i, j] = d[i - 1, j] + d[i - 1, j - ai]
class Solution {public: int findTargetSumWays(vector<int>& nums, int s) { int sum = accumulate(nums.begin(), nums.end(), 0); return sum < s || (s + sum) & 1 ? 0 : subsetSum(nums, (s + sum) >> 1); } int subsetSum(vector<int>& nums, int s) { int dp[s + 1] = { 0 }; dp[0] = 1; for (int n : nums) for (int i = s; i >= n; i--) dp[i] += dp[i - n]; return dp[s]; }};
细节
- 在算法1中,注意这道题有个坑点就是:第一个数为0的时候,其实有两种方案+0和-0,但是我们代码写的是
d[0][0]=1 ,因此,设置一个flag,第一个为0的时候我们的结果应该x2。并且后续若为0不用x2。 - 在算法2中,滚动数组优化空间。
- Leetcode编程题解:494. Target Sum
- LeetCode 494 Target Sum 题解
- LeetCode 494. Target Sum
- [LeetCode]494. Target Sum
- [leetcode]494. Target Sum
- Leetcode 494. Target Sum
- Leetcode-494. Target Sum
- Leetcode 494. Target Sum
- leetcode-494. Target Sum
- leetcode:494. Target Sum
- (LeetCode) 494. Target Sum
- LeetCode 494. Target Sum
- leetcode 494. Target Sum
- LeetCode 494. Target Sum
- LeetCode 494. Target Sum
- LeetCode 494. Target Sum
- [leetcode] 494. Target Sum
- [LeetCode] 494. Target Sum
- 计算表达式
- MSSQL:链接服务器
- 【Python】4“list和tuple集合“
- 机器学习之聚类算法k-means
- ALTER TABLE的用法
- Leetcode编程题解:494. Target Sum
- Git开篇
- 书架(一)
- windows 删除服务
- POJ 1702 Eva's Balance 笔记
- 几个你不得不知的经典名词解释.
- 配置Cocos Studio anroid环境问题
- HDU 5973 博弈
- HAProxy