1 题目描述

2  解题思路

  • 如果解决一个问题有多个步骤,每一个步骤有多种方法,题目又要我们找出所有的方法,可以使用回溯算法;
  • 回溯算法是在一棵树上的 深度优先遍历(因为要找所有的解,所以需要遍历);
  • 组合问题,相对于排列问题而言,不计较一个组合内元素的顺序性(即 [1, 2, 3] 与 [1, 3, 2] 认为是同一个组合),因此很多时候需要按某种顺序展开搜索,这样才能做到不重不漏。

既然是树形问题上的 深度优先遍历,因此首先画出树形结构。

例如输入:n = 4, k = 2,我们可以发现如下递归结构:

如果组合里有 1 ,那么需要在 [2, 3, 4] 里再找 1个数;
如果组合里有 2 ,那么需要在 [3, 4] 里再找 1数。注意:这里不能再考虑 1,因为包含 1 的组合,在第 1 种情况中已经包含。
依次类推(后面部分省略),以上描述体现的 递归 结构是:在以 n 结尾的候选数组里,选出若干个元素。画出递归结构如下图:

参考:https://leetcode-cn.com/problems/combinations/solution/hui-su-suan-fa-jian-zhi-python-dai-ma-java-dai-ma-/

2.1  未剪枝回溯

class Solution:def combine(self, n: int, k: int) -> List[List[int]]:res = []def backtrace(i,tmp):if len(tmp) == k:res.append(tmp)returnfor j in range(i,n+1):backtrace(j+1,tmp+[j])backtrace(1,[])return res

这里backtrace(i,lst)的意思是:在[1,i)里面,我们已经找到了一个排序lst(最后一个数就是i-1)。然后我们在[i,n]里面找一个点,作为排序的下一个点。

当我们lst的长度已经是k的时候,满足条件,就可以将这个序列放入我们要返回的部分了

这样查找是不会有重复的序列的。

2.2 剪枝回溯

但是,上述方法会有很多地方存在冗余,当我们剩余没有查看的序列的长度比我们还需要取得元素个数要少的时候,那么即使后面整个序列中的元素全部取出来,也不能达到条件。那么这一部分的backtrace就可以不用考虑了。

剪枝后的代码如下:

class Solution:def combine(self, n: int, k: int) -> List[List[int]]:res = []def backtrace(i,tmp):if len(tmp) == k:res.append(tmp)returnfor j in range(i,n+1):if(len(tmp)+n-j+1<k):returnbacktrace(j+1,tmp+[j])backtrace(1,[])return res

多了一句if(len(tmp)+n-j+1<k):,就是来判断剩余序列的长度是否满足要求的

可以看到,时间复杂度小了很多

2.3 写代码的时候的一个小坑

一开始我是这么写的,然后报错了

class Solution:def combine(self, n: int, k: int) -> List[List[int]]:tmp=[]ans=[]def dfs(idx):if(len(tmp)+(n-idx+1)<k):returnif(len(tmp)==k):ans.append(tmp)returntmp.append(idx)dfs(idx+1)tmp.pop()dfs(idx+1)dfs(1)return(ans)

从逻辑上看,也没有问题,但是注意一点,就是append(tmp) append的是一个引用,所以append里面的值会是一样的。

稍微修改一下,就对了

class Solution:def combine(self, n: int, k: int) -> List[List[int]]:ans=[]def dfs(idx,tmp):if(len(tmp)+(n-idx+1)<k):returnif(len(tmp)==k):ans.append(tmp)returndfs(idx+1,tmp)tmp1=tmp+[idx]dfs(idx+1,tmp1)dfs(1,[])return(ans)

文巾解题 77. 组合相关推荐

  1. 文巾解题 175. 组合两个表

    1 题目描述 2 解题思路 2.1 方法1:不用JOIN SELECTFirstName, LastName, (SELECT City FROM Address a WHERE a.PersonId ...

  2. 文巾解题 15. 三数之和

    1 题目描述 2 解题思路 2.1 使用两数之和函数 这种做法目前超时了,如果大家有想到合适的减时间/剪枝的方法,欢迎私信or评论~ 两数之和的方法见文巾解题 1. 两数之和_刘文巾的博客-CSDN博 ...

  3. 文巾解题 面试题 01.04. 回文排列

    1 题目描述 2 解题思路 2.1 哈希表 创建一个哈希表,记录每个元素出现的次数.如果出现次数为奇数的元素只有一个或者没有,那么就是一个回文排列 class Solution:def canPerm ...

  4. 文巾解题 342. 4的幂

    1 题目描述 2 解题思路 2.1 方法1 判断log函数的结果是不是整数 class Solution:def isPowerOfFour(self, n: int) -> bool:if(n ...

  5. 文巾解题 477. 汉明距离总和

    1 题目描述 2 解题思路 2.1 暴力两两比较 两个数字之间的汉明距离可以使用 文巾解题 461. 汉明距离_刘文巾的博客-CSDN博客 中的任何一种方法,但是因为这个是两两比较,时间复杂度比较高, ...

  6. 文巾解题 1035. 不相交的线

    1 题目描述 2 解题思路 k条互不相交的直线分别连接了数组 nums1和nums2的 k 对相等的元素,而且这 k 对相等的元素在两个数组中的相对顺序是一致的,因此,这 k 对相等的元素组成的序列即 ...

  7. 文巾解题 278. 第一个错误的版本

    1 题目描述 2 解题思路 二分查找见:二分查找详解_刘文巾的博客-CSDN博客 class Solution(object):def firstBadVersion(self, n):left=1r ...

  8. 文巾解题 704. 二分查找

    1 题目描述 2 解题思路 二分查找见: 二分查找详解_刘文巾的博客-CSDN博客 class Solution(object):def search(self, nums, target):left ...

  9. 文巾解题 627. 变更性别

    1 题目描述 2 解题思路 回顾一下 UPDATE语句 2.1 CASE语句 回顾一下CASE语句(见数据库笔记: SQL_刘文巾的博客-CSDN博客 第六节) UPDATE salary SET s ...

最新文章

  1. java poi 读取xlsx文件_使用POI读取xlsx文件(SXSSFWorkbook)
  2. vue部署到服务器 接口调用不了_Python 调用 Azure API 实现服务器自动部署
  3. WINDOW下,node.js的安装
  4. [03] 为什么要使用异常机制
  5. 全国计算机等级考试题库二级C操作题100套(第40套)
  6. 深度解析,教你如何打造自动驾驶的数据闭环
  7. Redmi Note 11系列来势汹汹,一“机”打尽更多看不见的旗舰猛料
  8. 一篇文章搞懂filebeat(ELK)
  9. 【POJ】【2125】Destroying the Graph
  10. oracle 关系 表 视图_在Oracle数据库中,表和视图的区别与联系
  11. 【Chapter 1】什么是软件架构
  12. WinDirStat – 硬盘空间都用在哪里了
  13. 微软产品内部协议大公开
  14. 大量贴图采样限制下的渲染处理方法
  15. 瑞莎 Renesas Flash烧录
  16. 2的32次方减1用python_3.Python入门
  17. 122、影响爆炸极限的因素
  18. [Datawhale-李宏毅机器学习-39期]-005-网络设计技巧
  19. matlab中条件数无穷大报错,matlab求条件数
  20. 再次写给我们这些浮躁的程序员

热门文章

  1. C 语言指针 5 分钟教程
  2. centos6.5下安装配置ELK及收集nginx日志
  3. Unity C#单例模式的实现
  4. Android Material Design :LinearLayoutCompat添加分割线divider
  5. android开发 java与c# 兼容AES加密
  6. 利用SSH端口转发功能实现X转发
  7. sourceinsight如何显示完整文件路径
  8. RESTful API的理解
  9. C++如何把字符串转化为数字?
  10. tcp/ip 协议栈Linux源码分析四 IPv4分片 ip_fragment函数分析