C++回溯算法中的全排列问题分析探讨
作者:清风何渡
递归中遇到一个问题全排列的问题,我看见回溯特别神奇,特此记录一下。对比一下深度优先搜索与广度优先搜索,个人感觉这里的回溯像是一种递归树中的深度优先搜索的算法,他不断构造往下延伸的深度,使其达到完全编列
一、全排列
全排列的特点就是:解放了index(每次遍历都从0开始),但是解放index的同时,又捆绑了used数组,记录已经出现过的元素
class Solution { private: vector<int> path; vector<vector<int>> result; int used[7]={0}; void backtracking(vector<int>& nums){ if(path.size()==nums.size()){ result.push_back(path); return; } for(int i=0;i<nums.size();i++){ if(used[i]==1) continue; path.push_back(nums[i]); used[i]=1; backtracking(nums); used[i]=0; path.pop_back(); } } public: vector<vector<int>> permute(vector<int>& nums) { backtracking(nums); return result; } };
二、全排列II
本题与全排列唯一不同在于需要去重这题与上一题唯一区别在于输入样例为可重复序列,且要求输出样例不重复
对于全排列问题,模板是设置used数组,只有used[i]==0时,才能选择该元素
对于去重问题,模板是先对nums排序,再判断nums[i]与nums[i-1]是否相等
根据全排列问题模板,设置used数组,只有used[i]==0时才可以选择
根据去重模板,先对nums排序,再判断nums[i]与nums[i-1]是否相等
但是全排列的去重没那么简单,因为全排列i是从0开始遍历,因此还要记录同一层当前已经访问到哪儿了,同一层不可以重复,但是同一树枝可以重复
但是不必再设置index,因为used数组可以兼任这个功能
如果used[i-1]==1,说明在同一个树枝访问过nums[i-1],同一树枝可以重复
如果used[i-1]==0,说明在同一层访问过nums[i-1],同一层不可以重复
很绕~
class Solution { private: vector<int> path; vector<vector<int>> result; int used[9]={0}; void backtracking(vector<int>& nums){ if(path.size()==nums.size()){ result.push_back(path); return; } for(int i=0;i<nums.size();i++){ if(i>0&&nums[i]==nums[i-1]&&used[i-1]==0) continue; if(used[i]==0){ path.push_back(nums[i]); used[i]=1; backtracking(nums); used[i]=0; path.pop_back(); } } } public: vector<vector<int>> permuteUnique(vector<int>& nums) { sort(nums.begin(),nums.end()); backtracking(nums); return result; } };
到此这篇关于C++回溯算法中的全排列问题分析探讨的文章就介绍到这了,更多相关C++回溯算法全排列内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!