Given an integer array with all positive numbers and no duplicates, find the number of possible combinations that add up to a positive integer target.

Example:

nums = [1, 2, 3]
target = 4 The possible combination ways are:
(1, 1, 1, 1)
(1, 1, 2)
(1, 2, 1)
(1, 3)
(2, 1, 1)
(2, 2)
(3, 1) Note that different sequences are counted as different combinations. Therefore the output is 7.

Follow up:
What if negative numbers are allowed in the given array?
How does it change the problem?
What limitation we need to add to the question to allow negative numbers?

Credits:
Special thanks to @pbrother for adding this problem and creating all test cases.

这道题是组合之和系列的第四道,博主开始想当然的以为还是用递归来解,结果写出来发现 TLE 了,的确 OJ 给了一个 test case 为 [4,1,2] 32,这个结果是 39882198,用递归需要好几秒的运算时间,实在是不高效,估计这也是为啥只让返回一个总和,而不是返回所有情况,不然机子就爆了。而这道题的真正解法应该是用 DP 来做,解题思想有点像之前爬梯子的那道题 Climbing Stairs,这里需要一个一维数组 dp,其中 dp[i] 表示目标数为i的解的个数,然后从1遍历到 target,对于每一个数i,遍历 nums 数组,如果 i>=x, dp[i] += dp[i - x]。这个也很好理解,比如说对于 [1,2,3] 4,这个例子,当计算 dp[3] 的时候,3可以拆分为 1+x,而x即为 dp[2],3也可以拆分为 2+x,此时x为 dp[1],3同样可以拆为 3+x,此时x为 dp[0],把所有的情况加起来就是组成3的所有情况了,参见代码如下:

解法一:

class Solution {
public:
int combinationSum4(vector<int>& nums, int target) {
vector<int> dp(target + );
dp[] = ;
for (int i = ; i <= target; ++i) {
for (auto a : nums) {
if (i >= a) dp[i] += dp[i - a];
}
}
return dp.back();
}
};

如果 target 远大于 nums 数组的个数的话,上面的算法可以做适当的优化,先给 nums 数组排个序,然后从1遍历到 target,对于i小于数组中的数字x时,直接 break 掉,因为后面的数更大,其余地方不变,参见代码如下:

解法二:

class Solution {
public:
int combinationSum4(vector<int>& nums, int target) {
vector<int> dp(target + );
dp[] = ;
sort(nums.begin(), nums.end());
for (int i = ; i <= target; ++i) {
for (auto a : nums) {
if (i < a) break;
dp[i] += dp[i - a];
}
}
return dp.back();
}
};

我们也可以使用递归+记忆数组的形式,不过这里的记忆数组用的是一个 HashMap。在递归函数中,首先判断若 target 小于0,直接返回0,若 target 等于0,则返回1。若当前 target 已经在 memo 中存在了,直接返回 memo 中的值。然后遍历 nums 中的所有数字,对每个数字都调用递归,不过此时的 target 要换成 target-nums[i],然后将返回值累加到结果 res 中即可,参见代码如下:

解法三:

class Solution {
public:
int combinationSum4(vector<int>& nums, int target) {
unordered_map<int, int> memo;
return helper(nums, target, memo);
}
int helper(vector<int>& nums, int target, unordered_map<int, int>& memo) {
if (target < ) return ;
if (target == ) return ;
if (memo.count(target)) return memo[target];
int res = , n = nums.size();
for (int i = ; i < n; ++i) {
res += helper(nums, target - nums[i], memo);
}
return memo[target] = res;
}
};

Github 同步地址:

https://github.com/grandyang/leetcode/issues/377

类似题目:

Combination Sum

Combination Sum II

Combination Sum III

参考资料:

https://leetcode.com/problems/combination-sum-iv/

https://leetcode.com/problems/combination-sum-iv/discuss/85079/My-3ms-Java-DP-solution

https://leetcode.com/problems/combination-sum-iv/discuss/85036/1ms-Java-DP-Solution-with-Detailed-Explanation

https://leetcode.com/problems/combination-sum-iv/discuss/85120/C%2B%2B-template-for-ALL-Combination-Problem-Set

LeetCode All in One 题目讲解汇总(持续更新中...)

[LeetCode] Combination Sum IV 组合之和之四的更多相关文章

  1. [LeetCode] 377. Combination Sum IV 组合之和之四

    Given an integer array with all positive numbers and no duplicates, find the number of possible comb ...

  2. [LeetCode] 377. Combination Sum IV 组合之和 IV

    Given an integer array with all positive numbers and no duplicates, find the number of possible comb ...

  3. [LeetCode] Combination Sum III 组合之和之三

    Find all possible combinations of k numbers that add up to a number n, given that only numbers from ...

  4. [LeetCode] Combination Sum II 组合之和之二

    Given a collection of candidate numbers (C) and a target number (T), find all unique combinations in ...

  5. [Leetcode] combination sum ii 组合之和

    Given a collection of candidate numbers ( C ) and a target number ( T), find all unique combinations ...

  6. 377 Combination Sum IV 组合之和 IV

    Given an integer array with all positive numbers and no duplicates, find the number of possible comb ...

  7. [LeetCode] 216. Combination Sum III 组合之和 III

    Find all possible combinations of k numbers that add up to a number n, given that only numbers from ...

  8. [leetcode]40. Combination Sum II组合之和之二

    Given a collection of candidate numbers (candidates) and a target number (target), find all unique c ...

  9. [LeetCode] 40. Combination Sum II 组合之和 II

    Given a collection of candidate numbers (candidates) and a target number (target), find all unique c ...

随机推荐

  1. JQuery中ajax的相关方法总结

    前提条件 话说是jquery中的ajax方法,那么前提条件当然是引入jquery啦. <script src="http://libs.baidu.com/jquery/1.9.0/j ...

  2. 前端精选文摘:BFC 神奇背后的原理

    BFC 已经是一个耳听熟闻的词语了,网上有许多关于 BFC 的文章,介绍了如何触发 BFC 以及 BFC 的一些用处(如清浮动,防止 margin 重叠等).虽然我知道如何利用 BFC 解决这些问题, ...

  3. SELECT TOP 1 比不加TOP 1 慢的原因分析以及SELECT TOP 1语句执行计划预估原理

    本文出处:http://www.cnblogs.com/wy123/p/6082338.html 现实中遇到过到这么一种情况: 在某些特殊场景下:进行查询的时候,加了TOP 1比不加TOP 1要慢(而 ...

  4. 来,一起让我们越来越懒,面向CSS、JS未来编程。(9.28已更新)

    2016.10.29更新 本文存在大量的错误,仅供参考. 不知不觉在前端领域马上一个年头就要过去了,然而再看看自己的代码,果然够烂,那么为什么代码一直没有用面向对象的思维去写CSS呢?首先有两点:一点 ...

  5. Oracle 中的sql函数以及分页

    SELECT LPAD(,'*.') "LPAD example" FROM DUAL; 1.分页查询 (1)方法一:使用  between  and 来实现分页 select * ...

  6. 2011奥斯卡最佳纪录片《监守自盗(Inside Job)》小结

    影片探讨了2008年金融危机产生的原因. 美国忽略1933年的旧法律,立新法,以放松金融监管. 投资银行被允许更高的杠杆率,33:1,也就是说,投资物跌价3%就会导致破产. 投资银行放贷,但是转手将贷 ...

  7. 《高性能javascript》 领悟随笔之-------DOM编程篇(二)

    <高性能javascript> 领悟随笔之-------DOM编程篇二 序:在javaSctipt中,ECMASCRIPT规定了它的语法,BOM实现了页面与浏览器的交互,而DOM则承载着整 ...

  8. js正则表达式校验非负整数:^\d+$ 或 ^[1-9]\d*|0$

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  9. WPF多源绑定

    将控件绑定到多个数据源,ListBox绑定到一个集合,其中每一项绑定到集合中对象的两个属性,并对绑定进行了格式化. <ListBox ItemsSource="{StaticResou ...

  10. Mac OS X搭建C#开发环境

    在Mac下想要用C#语言的话,首先得有个跨平台的.Net环境-Mono http://www.mono-project.com/ 有了Mono平台之后,还得有一个好工具:目前比较好的IDE是Xmari ...