代码随想录 | Day32 | 回溯算法:排列问题
主要学习内容:
1.复习树枝去重
2.复习树层去重
46.全排列
46. 全排列 - 力扣(LeetCode)
解法思路:
首先通过前面的学习,我们知道,每层递归函数的for循环是用来形成树形结构这一层的所有结点(比如main里面的递归函数的for循环形成了树形结构的第二层,剩下的结点都是递归得来的)
这道题的全排列,和组合问题最大的区别就是
1.[1,2,3]和[1,3,2]不是一个东西
2.因为[2,1,3]这种结果的存在,使得选了2以后要继续选1,说明每层递归函数的for循环的i都要从0开始而不是index,并且由于选了2了不能重复选择,在下面的函数里面碰到了2要跳过
由此可见,我们还需要一个used来记录我们已经选过的值(这就是树枝去重)
1.函数参数和返回值
1 2
| vector<vector<int>> res; void backtracking(vector<int>& nums,vector<int> path,vector<bool> used)
|
res存放结果
path存放目前放入的数
nums题目数组
used标记我们已经放过的数避免重复
2.终止条件
由全排列性质易知。
1 2 3 4 5
| if(path.size()==nums.size()) { res.push_back(path); return; }
|
3.本层代码逻辑
因为是全排列,每层递归函数的for循环都要把整个数组遍历一遍
used初始化全为false,选过的置为true
每当遇到false才会进入下层,将nums[i]压入path,used[i]置为true,遇到true直接跳过本次循环
1 2 3 4 5 6 7 8 9 10 11
| for(int i=0;i<nums.size();i++) { if(used[i]==false) { path.push_back(nums[i]); used[i]=true; backtracking(nums,path,used); path.pop_back(); used[i]=false; } }
|
完整代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| class Solution { public: vector<vector<int>> res; void backtracking(vector<int>& nums,vector<int> path,vector<bool> used) { if(path.size()==nums.size()) { res.push_back(path); return ; } for(int i=0;i<nums.size();i++) { if(used[i]==false) { path.push_back(nums[i]); used[i]=true; backtracking(nums,path,used); path.pop_back(); used[i]=false; } } } vector<vector<int>> permute(vector<int>& nums) { vector<int> path; vector<bool> used(nums.size(),false); backtracking(nums,path,used); return res; } };
|
47.全排列II
47. 全排列 II - 力扣(LeetCode)
思路:
这题是说明在树层之间不能有重复的,
比如[1,1,2],树形结构中的第二层(选择有1,1,2)直接把第二个1的分支给砍掉
那么就只需在上一题的基础上加上树层去重即可。
在40.组合总和和90子集II都写过,这里不再赘述
1 2
| if(i>0&&nums[i]==nums[i-1]&&used[i-1]==false) continue;
|
完整代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| class Solution { public: vector<vector<int>> res; void backtracking(vector<int>& nums,vector<int> path,vector<bool> used) { if(path.size()==nums.size()) { res.push_back(path); return ; } for(int i=0;i<nums.size();i++) { if(i>0&&nums[i]==nums[i-1]&&used[i-1]==false) continue; if(used[i]==false) { path.push_back(nums[i]); used[i]=true; backtracking(nums,path,used); path.pop_back(); used[i]=false; } } } vector<vector<int>> permuteUnique(vector<int>& nums) { vector<int> path; vector<bool> used(nums.size(),false); sort(nums.begin(),nums.end()); backtracking(nums,path,used); return res; } };
|