文章目录

  • 1 题目
  • 2 解决方案
    • 2.1 思路
    • 2.2 图解
    • 2.3 时间复杂度
    • 2.4 空间复杂度
  • 3 源码

1 题目

题目:数字组合(Combination Sum)
描述:给定一个候选数字的集合 candidates 和一个目标值 target。 找到 candidates 中所有的和为 target 的组合。在同一个组合中, candidates 中的某个数字出现次数不限。

  1. 所有数值 (包括 target ) 都是正整数.
  2. 返回的每一个组合内的数字必须是非降序的.
  3. 返回的所有组合之间可以是任意顺序.
  4. 解集不能包含重复的组合.

lintcode题号——135,难度——medium

样例1:

输入: candidates = [2, 3, 6, 7], target = 7
输出: [[7], [2, 2, 3]]

样例2:

输入: candidates = [1], target = 3
输出: [[1, 1, 1]]

2 解决方案

2.1 思路

  首先为了防止结果重复,需要进行去重的步骤,可以先在原序列中去重,因为按照题意,[m,m,m,n][m,n]两个序列在题目中是等价的,也可以之后在递归过程中进行去重。
  每次从排好序的序列头取元素,可以对同一元素取多次,直到取出的组合和为目标值,需要遍历所有的可能,这样的操作能够想到使用深度优先搜索来解决问题。代码中注意递归的三要素(定义、拆解、出口)即可。

DFS常用于需要遍历出所有解的场景中,例如求所有子集、得到所有组合、全排列等经典问题。

2.2 图解

candidates = [2, 3, 6, 7], target = 7的情况下,深度优先搜索的图如下:

#mermaid-svg-SkMjGa5ISGnvkMIs {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-SkMjGa5ISGnvkMIs .error-icon{fill:#552222;}#mermaid-svg-SkMjGa5ISGnvkMIs .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-SkMjGa5ISGnvkMIs .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-SkMjGa5ISGnvkMIs .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-SkMjGa5ISGnvkMIs .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-SkMjGa5ISGnvkMIs .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-SkMjGa5ISGnvkMIs .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-SkMjGa5ISGnvkMIs .marker{fill:#333333;stroke:#333333;}#mermaid-svg-SkMjGa5ISGnvkMIs .marker.cross{stroke:#333333;}#mermaid-svg-SkMjGa5ISGnvkMIs svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-SkMjGa5ISGnvkMIs .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-SkMjGa5ISGnvkMIs .cluster-label text{fill:#333;}#mermaid-svg-SkMjGa5ISGnvkMIs .cluster-label span{color:#333;}#mermaid-svg-SkMjGa5ISGnvkMIs .label text,#mermaid-svg-SkMjGa5ISGnvkMIs span{fill:#333;color:#333;}#mermaid-svg-SkMjGa5ISGnvkMIs .node rect,#mermaid-svg-SkMjGa5ISGnvkMIs .node circle,#mermaid-svg-SkMjGa5ISGnvkMIs .node ellipse,#mermaid-svg-SkMjGa5ISGnvkMIs .node polygon,#mermaid-svg-SkMjGa5ISGnvkMIs .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-SkMjGa5ISGnvkMIs .node .label{text-align:center;}#mermaid-svg-SkMjGa5ISGnvkMIs .node.clickable{cursor:pointer;}#mermaid-svg-SkMjGa5ISGnvkMIs .arrowheadPath{fill:#333333;}#mermaid-svg-SkMjGa5ISGnvkMIs .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-SkMjGa5ISGnvkMIs .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-SkMjGa5ISGnvkMIs .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-svg-SkMjGa5ISGnvkMIs .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-svg-SkMjGa5ISGnvkMIs .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-SkMjGa5ISGnvkMIs .cluster text{fill:#333;}#mermaid-svg-SkMjGa5ISGnvkMIs .cluster span{color:#333;}#mermaid-svg-SkMjGa5ISGnvkMIs div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-SkMjGa5ISGnvkMIs :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}

null
2
3
6
7
2
3
6
3
6
6
3
6
3
3
7 = 7
2+2+3=7
已超过7
已超过7
已超过7
已超过7
已超过7
已超过7

2.3 时间复杂度

  深度优先搜索的时间复杂度是逻辑图上的节点数(即所有元素的组合数,n个元素,每个元素都有取或不取两种可能,所以是2的n次方)与处理每个节点的耗时(for循环n次)的乘积,该题的算法的时间复杂度为O(2^n * n)。

深度优先搜索的时间复杂度计算没有通用的方式,只能根据具体题目计算,可以理解成看作答案个数与构造每个答案花费的时间的乘积。

2.4 空间复杂度

  使用了vector数据结构保存节点,算法的空间复杂度为O(n)。

3 源码

细节:

  1. 去重有两种方式,在原序列中先去重,或者在dfs递归中判断条件跳过重复。
  2. dfs过程中去重,该题在dfs内部判断时i != 0与i != startIndex都可行。
  • i与0比较的意义是防止i-1越界,防止从原序列中获取的每个元素与上一个元素相同,完全等价于在原序列中去重。
  • i与startIndex比较拥有更深的意义,它判断每层的非首元素和原序列前一个元素是否相同,首先是防止i-1越界,它能够防止同一层级中出现相同的元素,但不会禁止各个分支的第一个分叉(即i=startIndex)中出现与原序列前一个元素重复的元素。
  • 在该题中使用i != 0更直观,但i != startIndex的情况更加通用,之后的题会用来处理同一层级出现相同元素的情况。

C++版本:

/**
* @param candidates: A list of integers
* @param target: An integer
* @return: A list of lists of integers
*/
vector<vector<int>> combinationSum(vector<int> &candidates, int target) {// write your code herevector<vector<int>> results;if (candidates.empty()){return results;}// 因为要求结果是不降序的,所以先对原序列排序sort(candidates.begin(), candidates.end());// 防止答案中有重复,先把序列中的重复值去除//vector<int> newCandidates = removeDuplicate(candidates);vector<int> path;dfs(candidates, path, 0, target, results);return results;
}void dfs(vector<int> & candidates, vector<int> path, int startIndex, int remainTarget, vector<vector<int>> & results)
{if (remainTarget == 0){results.push_back(path);return;}for (int i = startIndex; i < candidates.size(); i++){// 如果序列中有重复的数,则跳过,防止结果产生重复,i!=0为了防止i-1越界(也可以在原序列中先去重)if (i != 0 /*startIndex*/ && candidates.at(i) == candidates.at(i - 1)){continue;}// 结果超过目标值,则停止,防止后续的无效搜索if (remainTarget < candidates.at(i)){break;}path.push_back(candidates.at(i));// 可以重复取同一个值,所以递归依然从i开始,而不是i+1dfs(candidates, path, i, remainTarget - candidates.at(i), results);path.pop_back();}
}//vector<int> removeDuplicate(vector<int> & candidates)
//{
//    int index = 0;
//    for (int i = 1; i < candidates.size(); i++)
//    {
//        if (candidates.at(index) != candidates.at(i))
//        {
//            candidates.at(++index) = candidates.at(i);
//        }
//    }//    vector<int> result;
//    result.insert(result.end(), candidates.begin(), candidates.begin() + index + 1);
//    return result;
//}

36 数字组合(Combination Sum)相关推荐

  1. 40. Combination Sum II 组合总和 II

    给定一个数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合. candidates 中的每个数字在每个组合中只能使用一次. ...

  2. 【LeetCode】#39组合总和(Combination Sum)

    [LeetCode]#39组合总和(Combination Sum) 加粗样式 给定一个无重复元素的数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数 ...

  3. python数字组合算法_python猜数字游戏快速求解解决方案

    python猜数字游戏快速求解解决方案.使用方法: 1. 保存代码为guessall.py 2. 执行python guessall.py > result.txt 3. 打开result.tx ...

  4. 【动态规划】LeetCode 377. Combination Sum IV

    LeetCode 377. Combination Sum IV Solution1: 我的未能AC的答案 题目描述的和前几道题差不多,但实际上不能用DFS来做(会超时),要用动态规划,还是记录一下吧 ...

  5. 拼多多——多多的数字组合

    多多的数字组合 题目 思路 代码 结果 题目 多多君最近在研究某种数字组合: 定义为:每个数字的十进制表示中(0~9),每个数位各不相同且各个数位之和等于N. 满足条件的数字可能很多,找到其中的最小值 ...

  6. LintCode 数字组合 题解

    数字组合 描述 笔记 数据 评测 给出一组候选数字(C)和目标数字(T),找到C中所有的组合,使找出的数字和为T.C中的数字可以无限制重复被选取. 例如,给出候选数组[2,3,6,7]和目标数字7,所 ...

  7. (算法)求数组中数字组合(可多值组合)相加最接近目标数的组合(可能多个)

      今天没事,撸一道算法题   题目要求: 给出一个升序排序的可能重复值的数字数组和一个目标值其中目标值大于数组中最小数,求数组中数字组合(可多值组合)相加最接近目标数的组合(可能多个)不考虑空间复杂 ...

  8. LC39 Combination Sum

    还是利用深搜的思想,注意一个元素可以取无数次.而LC40 Combination Sum II 就有次数限制,有次数限制的情况下可以先判断一个数是否与它前面的数相等,若相等则跳过该元素,直到找到一个数 ...

  9. 组合学:26个字母(含大小写)和10个数字组合为4位串的可能性测算

    使用26个字母(含大小写,实际为52个字母)和10个数字组合一个4位的串码,问有多少种组合? 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k' ...

最新文章

  1. 太赞了!NumPy 手写所有主流 ML 模型,由普林斯顿博士后 David Bourgin打造的史上最强机器学习基石项目!...
  2. 搭建网络及服务器系统,网络服务器搭建与管理
  3. 奉劝各位的atas几句话,别怪我没提醒
  4. 【Java】强软弱虚四种引用,弱引用在ThreadLocal中的应用
  5. winston log 库如何创建 custom logger
  6. SAP ABAP编辑器里的Code Completion(代码自动完成)的等待时间设置
  7. 如何在机器学习项目中使用统计方法的示例
  8. java中的字符串_java中字符串的操作
  9. Vue3项目中使用AE+bodymovin+lottie的模式制作特效
  10. spring基础--注解配置ssm开发环境
  11. NLP自然语言处理干货贴
  12. 俞敏洪:度过有意义的生命(转)
  13. [全网首发]坚果Pro3 root教程 Magisk
  14. dns服务器 性能测试,dns服务器性能测试报告.docx
  15. 计算机主板清理,电脑主板脏了如何清洗电脑主板才是正确
  16. getAddrInfo与DNS域名解析与ping
  17. Win10 没有激活,如何改变任务栏位置
  18. ipad和android平板应用程序,安卓平板相比iPad有哪些优势和劣势?
  19. 单模SIW的设计步骤
  20. 解魔方机器人系列(一)kociemba算法

热门文章

  1. 程序员后端学习路线大体了解
  2. 【论文笔记】Encoding cloth manipulations using a graph of states and transitions
  3. 关于设计的一点思考:
  4. 浅析智能驾驶的发展现状和未来趋势
  5. HttpReques
  6. 应广单片机003烧录器万能烧录方法
  7. 维度数据建模的概念和术语
  8. CMA认证与CNAS认可的八大区别,你知道几个?
  9. ubuntu18分辨率变低,无法调整,最高只有1024*768
  10. DLX精确覆盖 hdu4069 Squiggly Sudoku