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] 377. Combination Sum IV 组合之和之四的更多相关文章

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

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

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

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

  3. 377 Combination Sum IV 组合之和 IV

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

  4. [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 ...

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

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

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

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

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

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

  8. Leetcode 377. Combination Sum IV

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

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

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

随机推荐

  1. 我的周记12——"站在现在看前人对未来的预测,很有意思"

    万里风云三尺剑,一庭花草半床书 聊聊最近很火的5G B站有个up主  老师好我叫何同学  优秀啊,点赞. 他做了一个5G测速的视频火啦 视频链接:https://www.bilibili.com/vi ...

  2. sitecore 如何创建一个渠道分类

    您可以通过渠道跟踪联系人与您的品牌的所有互动.您可以将渠道与广告系列活动相关联,以便跟踪联系人与您的品牌互动的方式.通过比较各个渠道的目标转化率,您可以了解哪些渠道可以带来更好的联系参与度.您可以在体 ...

  3. cmd控制台中文乱码解决办法

    1.打开cmd控制台,在命令行输入chcp后回车可以查看到当前的字符编码.如果是乱码的话,这时通常是936,代表的是GBK编码. 2.在命令行输入chcp 65001后回车.65001代表的是UTF- ...

  4. Java自学-集合框架 ArrayList常用方法

    ArrayList常用方法 步骤 1 : 增加 add 有两种用法: 第一种是直接add对象,把对象加在最后面 heros.add(new Hero("hero " + i)); ...

  5. SUSE12-SP2安装教程(虚拟机)

    创建虚拟机,安装系统,安装系统后的系统设置 创建虚拟机 将SUSE12-SP2镜像(大于3G)上传到虚拟机主机存储. 创建虚拟机创建虚拟机,CPU>=8核,内存>=16G(注:我这里仅演示 ...

  6. SQL注入:盲注

    盲注简介 所谓的盲注就是在服务器没有错误回显的时候完成的注入攻击. 服务器没有错误回显,对于攻击者来说缺少了非常重要的"调试信息". 盲注分类 1.布尔盲注 布尔很明显Ture和F ...

  7. qos-server can not bind localhost:22222, dubbo version: 2.6.0, current host: 127.0.0.1【问题解决】

    好吧,这个问题比较low,但是记录一下,以免后期遗忘. 说白了,这个问题就是端口被占用了. 问题: qos-server can not bind localhost:22222, dubbo ver ...

  8. Navicat Premium 详解

    Navicat是一套数据库管理工具,专为简化数据库的管理及降低系统管理成本而设. Navicat 是以直觉化的图形用户界面而建的,可以安全和简单地创建.组织.访问并共用信息.  Navicat Pre ...

  9. Gitlab批量迁移项目

    最近接到一个需求,要把一个Gitlab上边的项目全部导入到另外一个Gitlab,借鉴了网上的一个方法,成功实现. 参考链接:https://segmentfault.com/a/11900000159 ...

  10. JS高阶---浏览器内核

    不同浏览器的内核,不太一样 360双核切换机制 一般涉及到金钱交易时,会切换到Trident内核,因为IE内核安全性较稳 不涉及金钱利益时,则会使用webkit内核 (1)内核是由很多模块构成 注意: ...