494. Target Sum
来源:互联网 发布:剑灵猫猫捏脸数据 编辑:程序博客网 时间:2024/06/05 06:30
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.
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.
Subscribe to see which companies asked this question.
【问题分析】
1、该问题求解数组中数字只和等于目标值的方案个数,每个数字的符号可以为正或负(减整数等于加负数)。
2、该问题和矩阵链乘很相似,是典型的动态规划问题
3、举例说明: nums = {1,2,3,4,5}, target=3, 一种可行的方案是+1-2+3-4+5 = 3
该方案中数组元素可以分为两组,一组是数字符号为正(P={1,3,5}),另一组数字符号为负(N={2,4})
因此: sum(1,3,5) - sum(2,4) = target
sum(1,3,5) - sum(2,4) + sum(1,3,5) + sum(2,4) = target + sum(1,3,5) + sum(2,4)
2sum(1,3,5) = target + sum(1,3,5) + sum(2,4)
2sum(P) = target + sum(nums)
sum(P) = (target + sum(nums)) / 2
由于target和sum(nums)是固定值,因此原始问题转化为求解nums中子集的和等于sum(P)的方案个数问题
4、求解nums中子集合只和为sum(P)的方案个数(nums中所有元素都是非负)
该问题可以通过动态规划算法求解
举例说明:给定集合nums={1,2,3,4,5}, 求解子集,使子集中元素之和等于9 = new_target = sum(P) = (target+sum(nums))/2
定义dp[10]数组, dp[10] = {1,0,0,0,0,0,0,0,0,0}
dp[i]表示子集合元素之和等于当前目标值的方案个数, 当前目标值等于9减去当前元素值
当前元素等于1时,dp[9] = dp[9] + dp[9-1]
dp[8] = dp[8] + dp[8-1]
...
dp[1] = dp[1] + dp[1-1]
当前元素等于2时,dp[9] = dp[9] + dp[9-2]
dp[8] = dp[8] + dp[8-2]
...
dp[2] = dp[2] + dp[2-2]
当前元素等于3时,dp[9] = dp[9] + dp[9-3]
dp[8] = dp[8] + dp[8-3]
...
dp[3] = dp[3] + dp[3-3]
当前元素等于4时,
...
当前元素等于5时,
...
dp[5] = dp[5] + dp[5-5]
最后返回dp[9]即是所求的解
【AC代码】
class Solution { public: int findTargetSumWays(std::vector<int>& nums, int S) { int sum = std::accumulate(nums.begin(), nums.end(), 0); return sum < S || (S + sum) & 1 ? 0 : subsetSum(nums, (S+sum) >> 1); } int subsetSum(std::vector<int>& nums, int s) { int dp[s+1]; memset(dp, 0, sizeof(int)*(s+1)); dp[0] = 1; for(int n: nums) { for (int i = s; i >= n; --i) { dp[i] += dp[i-n]; } } return dp[s]; }};
参考内容:
https://discuss.leetcode.com/topic/76243/java-15-ms-c-3-ms-o-ns-iterative-dp-solution-using-subset-sum-with-explanation/2
https://discuss.leetcode.com/topic/63049/my-simple-c-dp-code-with-comments/2
- LeetCode 494. Target Sum
- [LeetCode]494. Target Sum
- 494. Target Sum
- [leetcode]494. Target Sum
- 494. Target Sum
- Leetcode 494. Target Sum
- 494. Target Sum -Medium
- 494. Target Sum
- Leetcode-494. Target Sum
- 494. Target Sum
- Leetcode 494. Target Sum
- 494. Target Sum
- leetcode-494. Target Sum
- 494. Target Sum
- 494. Target Sum
- 494. Target Sum
- 494. Target Sum
- 494. Target Sum
- QT实现文本转语音
- C# SendKeys用法
- MongoDB 增删改查与 Golang 的语法实现
- poj 2533 最大上升子序列
- 基础练习 数列排序
- 494. Target Sum
- Unity中的时间控制 - 时间倒退
- IOS10 Notification推送通知(二)
- Oracle AMM学习总结
- WPF字体图标——IconFont
- 如何获取windows DPI设置值(Set Custom Text Size)
- 割屏利器tmux
- BZOJ 1192, 鬼谷子的钱袋
- Delphi的四舍五入函数