77. 组合 - 递归
熟悉我的读者朋友都知道,我是面向思维做题,做题是为了保持时间复杂度、空间复杂度的敏感,顺便锻炼一下脑筋,把思维用代码表达出来。
题目的解法不止一种,我会记住一两种。我的选择标准是:思路简单,代码清晰
题目链接
给定两个整数 n 和 k,返回范围 [1, n] 中所有可能的 k 个数的组合。
你可以按 任何顺序 返回答案。
示例 1:
输入:n = 4, k = 2
输出:
[[2,4],[3,4],[2,3],[1,2],[1,3],[1,4],
]
示例 2:
输入:n = 1, k = 1
输出:[[1]]
提示:
1 <= n <= 20
1 <= k <= n
题目分析
这道题用递归来完成。
关于递归,建议看看极客时间,覃超老师用电影《盗梦空间》解释递归的框架:
public void dfs( param1, param2 ...) {第一部分:递归终止条件第二部分:做本层工作第三部分:潜入下一层第四部分:清理本层
}
这一道题的递归解法也差不多。
class Solution {List<List<Integer>> ans = new ArrayList<>();List<Integer> temp = new ArrayList<>();public List<List<Integer>> combine(int n, int k) {dfs(1,n,k);return ans;}public void dfs(int cur, int n, int k ) {// 第一部分:递归终止条件if (temp.size() == k ) {ans.add(new ArrayList<>(temp));return ;}if (cur == n + 1) {return;}// 第二部分:做本层工作temp.add(cur); // 选择当前元素// 第三部分:潜入下一层dfs(cur+1, n, k);temp.remove(temp.size()-1); // 不选当前元素// 再次潜入下一层dfs(cur+1, n ,k);// 第四部分:清理本层// ...无}}
这样做其实已经通过了。
第一个下潜结束,回到本层,然后从不选当前元素,到再次潜入下一层,这个过程称为 回溯
递归的过程是立体的
把递归的过程看成从1开始,选1和不选1,得到2个子树
在第二层,选2和不选2 ,又分别得到2个子树
第三层,选3和不选3,又分别得到2个子树
第四层,选4和不选4,又分别得到2个子树
对于一些明显不可能构成结果的子树,可以提前结束下潜,这种操作称之为 剪枝
剪枝的过程如下:
如果当前 temp 的大小为 s,未确定状态的区间 [cur, n] 的长度为 t,如果 s + t<k,那么即使 t 个都被选中,也不可能构造出一个长度为 k 的序列,故这种情况就没有必要继续向下递归,即我们可以在每次递归开始的时候做一次这样的判断:
if (temp.size() + (n - cur + 1) < k) {return;
}
最终代码
class Solution {List<List<Integer>> ans = new ArrayList<>();List<Integer> temp = new ArrayList<>();public List<List<Integer>> combine(int n, int k) {dfs(1,n,k);return ans;}public void dfs(int cur, int n, int k ) {// 第一部分:递归终止条件if (temp.size() == k ) {ans.add(new ArrayList<>(temp));return ;}if (cur == n + 1) {return;}// 根据题目条件,做一个小小的剪枝if (temp.size() + (n - cur + 1) < k) {return;} // 第二部分:做本层工作temp.add(cur); // 选择当前元素// 第三部分:潜入下一层dfs(cur+1, n, k);temp.remove(temp.size()-1); // 不选当前元素// 再次潜入下一层dfs(cur+1, n ,k);// 第四部分:清理本层// ...无}}
剪枝之后,减少了递归次数,优化了耗时。
TODO: 补充极客时间的链接,二叉树的图。补充提交记录的截图。
77. 组合 - 递归相关推荐
- 算法训练Day25 | LeetCode216. 组合总和III(和77.组合很像!);LeetCode17. 电话号码的字母组合(不同集合中组合)
目录 LeetCode216. 组合总和III 1. 思路 2. 代码实现 3. 剪枝 4. 复杂度分析 5. 思考与收获 LeetCode17. 电话号码的字母组合 1. 思路 2. 代码实现 3. ...
- 每日一道leetcode(python)77. 组合
每日一道leetcode(python)77. 组合 2021-08-25 给定两个整数 n 和 k,返回范围 [1, n] 中所有可能的 k 个数的组合.你可以按 任何顺序 返回答案.示例 1:输入 ...
- leetcode:77.组合
77. 组合 来源:力扣(LeetCode) 链接: https://leetcode.cn/problems/combinations 给定两个整数 n 和 k,返回范围 [1, n] 中所有可能的 ...
- 【算法leetcode每日一练】剑指 Offer II 080. 含有 k 个元素的组合 | 77. 组合
文章目录 剑指 Offer II 080. 含有 k 个元素的组合 | 77. 组合: 样例 1: 样例 2: 提示: 分析 题解 java c c++ python go rust javascri ...
- Day21||● 77. 组合
77. 组合 使用的是回溯算法.回溯算法很抽象,在递归的使用里边也算是比较难的,可以画一个树状图枚举一下.我们递归的操作其实就是在对树状图进行遍历.在每层的for循环里边其实有一个剪枝操作,就是如果我 ...
- 代码随想录【Day24】| 开始回溯!77. 组合
回溯的本质是穷举,穷举所有可能,然后选出我们想要的答案,如果想让回溯法高效一些,可以加一些剪枝的操作,但也改不了回溯法就是穷举的本质. 那么既然回溯法并不高效为什么还要用它呢? 因为没得选,一些问题能 ...
- 力扣 刷题77 组合排序,剪枝
77. 组合 难度中等451收藏分享切换为英文接收动态反馈 给定两个整数 n 和 k,返回 1 ... n 中所有可能的 k 个数的组合. 示例: 输入: n = 4, k = 2 输出: [[2,4 ...
- 代码随想录算法训练营第二十四天 | 理论基础、77. 组合
学习目标 学习回溯算法理论基础, 并进行练习 学习内容 回溯算法理论基础 文章链接:回溯算法理论基础 小结:回溯算法模板: void backtracking(参数) {if (终止条件) {存放结果 ...
- LeetCode.77. 组合
LeetCode.77. 组合 难度:中等 这道题属于回溯的经典题目: 回溯模板: void backtracking(参数) {if (终止条件) {存放结果;return;}for (选择:本层集 ...
- 代码随想录算法训练营第24天25天|● 77. 组合● 216.组合总和III ● 17.电话号码的字母组合
77组合 看完题后的思路 void f(数组,startIndex) 递归终止 if(startIndex数组长度||path.sizek){ if(path.size==k){ 加入} } 递归 f ...
最新文章
- Web Cookie详解
- 全网最新 Skywalking 6.1.0部署进k8s 包含springcloud测试用例
- 地表最强的MySQL安装一键式安装,信不信你下完我就给你装好!附各种Mysql安装失败的解决办法(什么你安装失败了?快来看这个)
- Xuggler开发教程
- spring整合atomikos实现分布式事务的方法示例_分布式事务一:基于数据库原生分布式事务方案实现...
- 计算机机器语言与高级语言转化,机器语言与汇编语言之间是怎么转化的?
- Leetcode 笔记 116 - Populating Next Right Pointers in Each Node
- CodeForces - 1610B Kalindrome Array
- 2022爱分析· 地产科技厂商全景报告
- eviews安装教程
- 【吐血整理,建议收藏】B站上有哪些值得反复观看的Java视频教程?
- supplicant
- 金仓数据库在 TPCE(dbt5,tpsE)测试框架方面的实践和突破
- Linux下安装ORACLE(一周成果、全是干货!)
- 一些概念名称的来历札记
- c语言字符就地逆置,高手看看我的C语言代码单链表实现就地逆置
- Rest Time for Mac(电脑休息提醒软件)
- 关于做PPT的一些总结
- CAN(Controller Area Network)通信介绍及其运作方法
- Ubuntu配置ftp