深度优先搜索和回溯结合后的终极模板
Posted Python与算法社区
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了深度优先搜索和回溯结合后的终极模板相关的知识,希望对你有一定的参考价值。
1 回顾
昨天 推送了一个深度搜索和回溯结合的题目和另4道类似题,今天,逐个分析后4道题,最后提炼出模板。
2 分析4道题
1) 集合内元素都不相同,求子集,举一个例子:
1 nums = [1,2,3], 子集为:
2 [
3 [3],
4 [1],
5 [2],
6 [1,2,3],
7 [1,3],
8 [2,3],
9 [1,2],
10 []
11]
实现代码:
1class Solution {
2 public List<List<Integer>> subsets(int[] nums) {
3 List<List<Integer>> list = new ArrayList<>();
4 Arrays.sort(nums);
5 dfs(list, new ArrayList<>(), nums, 0);
6 return list;
7 }
8
9 private void dfs(List<List<Integer>> list ,
10 List<Integer> temp,
11 int [] nums,
12 int start){
13 list.add(new ArrayList<>(temp));
14 for(int i = start; i < nums.length; i++){ //depth first search
15 temp.add(nums[i]);
16 dfs(list, temp, nums, i + 1); //start位置加1,重要!!!
17 temp.remove(temp.size() - 1); //出栈时依次移除末尾元素
18 }
19 }
20}
用上面代码跑出的打印出的结果如下所示,如上代码所示,因为是深度优先搜索,把以1为根的所有子集先找出,在找出以2为根的所有子集,最后找出以3为根的所有子集。
1[[],[1],[1,2],[1,2,3],[1,3],[2],[2,3],[3]]
短短的几行代码足以实现,可见递归的简洁性。
2) 集合内元素可能相同,求子集
1nums = [1,2,2], 子集为:
2
3[
4 [2],
5 [1],
6 [1,2,2],
7 [2,2],
8 [1,2],
9 []
10]
实现代码仅与上面【集合内元素都不相同,求子集】有一个差别:处理1和第一个2,1和第二个2的情况只取一种。
1class Solution {
2 public List<List<Integer>> subsetsWithDup(int[] nums) {
3 List<List<Integer>> list = new ArrayList<>();
4 Arrays.sort(nums);
5 dfs(list, new ArrayList<>(), nums, 0);
6 return list;
7 }
8
9 private void dfs(List<List<Integer>> list, List<Integer> temp, int [] nums, int start){
10 list.add(new ArrayList<>(temp));
11 for(int i = start; i < nums.length; i++){
12 if(i > start && nums[i] == nums[i-1]) //含有重复元素的子集
13 continue;
14 temp.add(nums[i]);
15 dfs(list, temp, nums, i + 1);
16 temp.remove(temp.size() - 1);
17 }
18 }
19}
打印结果的顺序如下:
1[[],[1],[1,2],[1,2,2],[2],[2,2]]
3) 求集合的不同组合序列
1[1,1,2] 的不同组合序列:
2
3[
4 [1,1,2],
5 [1,2,1],
6 [2,1,1]
7]
1class Solution {
2 public List<List<Integer>> permuteUnique(int[] nums) {
3 List<List<Integer>> list = new ArrayList<>();
4 Arrays.sort(nums);
5 dfs(list, new ArrayList<>(), nums, new boolean[nums.length]);
6 return list;
7 }
8
9 private void dfs(List<List<Integer>> list, List<Integer> temp, int [] nums, boolean [] used){
10 if(temp.size() == nums.length){
11 list.add(new ArrayList<>(temp));
12 }
13 else{
14 for(int i = 0; i < nums.length; i++){
15 if(used[i] ||
16 i > 0 && nums[i] == nums[i-1] && !used[i - 1])
17 continue;
18 used[i] = true;
19 temp.add(nums[i]);
20 dfs(list, temp, nums, used);
21 used[i] = false;
22 temp.remove(temp.size() - 1);
23 }
24 }
25 }
26}
1 class Solution {
2 public List<List<Integer>> subsetsWithDup(int[] nums) {
3 List<List<Integer>> list = new ArrayList<>();
4 Arrays.sort(nums);
5 dfs(list, new ArrayList<>(), nums, 0);
6 return list;
7 }
8
9 private void dfs(List<List<Integer>> list, List<Integer> temp, int [] nums, int start){
10 /*此处判断是否拿到一个可行解*/
11 list.add(new ArrayList<>(temp));
12
13 /*深度优先搜索*/
14 for(int i = start; i < nums.length; i++){
15 /*可行解的约束条件*/
16 if(i > start && nums[i] == nums[i-1]) //含有重复元素的子集
17 continue;
18 /*找到解的一部分元素,作为根元素*/
19 temp.add(nums[i]);
20 /*添加枝叶*/
21 dfs(list, temp, nums, i + 1);
22 /*枝叶出栈时需要的操作,必有的是退出枝叶*/
23 temp.remove(temp.size() - 1);
24 }
25 }
26}
学知识,送红包系列活动
预知是否获得红包,请参考获奖名单。
Python与机器学习算法频道
欢迎点赞和转发
以上是关于深度优先搜索和回溯结合后的终极模板的主要内容,如果未能解决你的问题,请参考以下文章