排列,组合,子集专题

排列组合的题用回溯法和递归基本可以解决,总结一下。
46.全排列

46

手动模拟全排列的思想,就是固定一个数,然后让后面的继续做全排列,为了保证排列不一样,需要保证固定的数不一样。
sol1

sol2

这两份代码其实是一样的,不过上面那份用了引用,多了个交换的操作,都是每次固定不同的左端,然后继续递归进行全排列。
非递归算法参见https://blog.csdn.net/u014106644/article/details/83988102
非递归算法

sol3.1

sol3.2

47.全排列II


47

47比46多了个序列可重复的条件,意味着我们需要在46题基础上做个去重的操作,然后我们考虑在上面的两个模板上分别改一下。

sol2

第三种非递归写法,和上面那道题代码只有一处不一样


sol1

28行不一样

  1. 下一个排列


    31

    这道题的写法就是非重全排列的非递归写法中的一次寻找


    sol1.1

    sol1.2

60第k个排列


60

这道题有两种解法,一种就是把模拟下一次排列K次,比较慢,第二种采取数学方法做。


sol1.1

sol1.2

数学方法:待补

77组合


77

这道题可以做个剪枝,在18到19行,主要还是采取了回溯法。
77

39组合总和
39

这道题和上面那道题的不同之处在于限制条件不同,但思想还是回溯法进行挑选,还是要注意剪枝
39

40.组合总和 II
40

和上一道区别是元素可重复,但只能用一次。
这道题有两种解法:
sol1.转换成上面一道题,把重复的元素理解为单个元素可以重复取多次
sol2.通过比较相邻的点来进行判断是否重复选取
sol1明显好理解一点,在记录重复取的次数可以用unordered_map来保存,O(1)复杂度读取,分2种情况,如果可重复次数>1,那么仍然可以重复取这个数,如果==1,那么直接跳到下一个数。


sol1.1

sol1.2

sol2.如果前一个数没选取,但选取的数和前一个重复时,这种情况可以不要,也算一个剪枝,但不太好想。
sol2

216组合总和 III
216
sol1

377组合总和 Ⅳ


377

tle

dfs复杂度太高了,t掉了,这道题没要求输出组合的结果,正确解法应该是dp,更确切的说记忆化dfs。


sol

78子集
78

sol

90子集 II


90

sol1

784字母大小写全排列


784

sol1.1

sol1.2

996正方形数组的数目


996

这道题就是47题全排列的改编版,进一步进行条件约束,注意边界。
sol1.1

sol1.2

排列是在原数组上两两交换,组合和子集是在容器里进行,子集是立刻输出,排列和组合是符合要求再输出

然后总而言之上面写的有点复杂,我们用标记数组的方式,用最简单的dfs的方式来写一遍,比较好理解
排列的题可以对path的位置做标记。。
46.code. https://leetcode-cn.com/submissions/detail/21611688/ (不重复排列) 输出字典序
47.code. https://leetcode-cn.com/submissions/detail/21612550/(重复排列)
组合的题
77.code.https://leetcode-cn.com/submissions/detail/21635210/ (不重复组合)
39.code. https://leetcode-cn.com/submissions/detail/18719647/ (重复组合总和)
40.code.https://leetcode-cn.com/submissions/detail/21638733/ (不重复组合总和)
216.code. https://leetcode-cn.com/submissions/detail/21639856/
377.code.https://leetcode-cn.com/submissions/detail/21641035/ (dp计数)
子集的题
78.code. https://leetcode-cn.com/submissions/detail/21641879/ (不重复子集)
90.code. (重复子集)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容