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. 再谈React.js实现原生js拖拽效果

    前几天写的那个拖拽,自己留下的疑问...这次在热心博友的提示下又修正了一些小小的bug,也加了拖拽的边缘检测部分...就再聊聊拖拽吧 一.不要直接操作dom元素 react中使用了虚拟dom的概念,目 ...

  2. 使用BitArray判断素数

    首先显示1024范围内的所有素数,然后显示输入的数是否是素数.1024 是代码中计算的素数的范围,可以修改.计算平方根,是为了确定一个基数的范围.1024的平方根是32,两个超过32 的数相乘,肯定大 ...

  3. [翻译+山寨]Hangfire Highlighter Tutorial

    前言 Hangfire是一个开源且商业免费使用的工具函数库.可以让你非常容易地在ASP.NET应用(也可以不在ASP.NET应用)中执行多种类型的后台任务,而无需自行定制开发和管理基于Windows ...

  4. java集合你了解多少?

    用了java集合这么久,还没有系统的研究过java的集合结构,今天亲自画了下类图,总算有所收获. 一.所有集合都实现了Iterable接口. Iterable接口中包含一个抽象方法:Iterator& ...

  5. spring源码:Aware接口(li)

    一.spring容器中的aware接口介绍 Spring中提供了各种Aware接口,比较常见的如BeanFactoryAware,BeanNameAware,ApplicationContextAwa ...

  6. 解决ngnix服务器上的Discuz!x2.5 Upload Error:413错误

    1.修改php.ini sudo nano /etc/php5/fpm/php.ini #打开php.ini找到并修改以下的参数,目的是修改上传限制 max_execution_time = 900 ...

  7. 5.1 JS中Object类型

    1.Object类型是引用类型中的一种. 2.创建Object实例(对象)的方式: 方式1:使用new操作符,后面跟上Object构造函数.如: var obj = new Object();//创建 ...

  8. linux中grep的应用

    h3 { color: rgb(255, 255, 255); background-color: rgb(30,144,255); padding: 3px; margin: 10px 0px } ...

  9. 弹出层layer的使用

    弹出层layer的使用 Intro layer是一款web弹层组件,致力于服务各个水平段的开发人员.layer官网:http://layer.layui.com/ layer侧重于用户灵活的自定义,为 ...

  10. 传统软件和SaaS,差异究竟在哪里

    这篇文章从创业起步阶段.产品形态和产品策略.市场竞争格局三个方面比较了中美 SaaS 领域的异同,在文章的最后,作者根据自己在 Box 的工作经历对在国内做 SaaS 的公司提出了四点建议. 我曾有幸 ...