leetcode 47.全排列II
题干
给定一个可包含重复数字的序列,返回所有不重复的全排列。
示例:
输入: [1,1,2]
输出:
[
[1,1,2],
[1,2,1],
[2,1,1]
]
题解
经典回溯算法
* 核心问题在重复数字序列的处理,需要在判断前加上i>0的判断,否则当i==0时就会出现nums[-1]的越界情况
* 还有一个核心在A代码块,推入一个答案后进行递归,在递归语句后将这个元素取出,对下一个元素进行递归
* 将ans设为函数引用参数可以提高效率,即将vector<vector>& ans作为dfs的参数传入
* (并不)其实这个解法的去重是不完全的,这个解法只能在单支递归中避免重复数据带来的答案重复,实际上在不同分支的递归中仍然可能出现重复结果,而且nums中的重复元素越多,这种重复性就越高
* 上述想法是错的,实际去重是能避免重复结果的
class Solution {
public:
vector<vector<int>> ans;
vector<int> vis;//全局自动置0
void dfs(int now,vector<int> nums,vector<int>& singleArray){
if(now==nums.size())
{
ans.push_back(singleArray);
return;
}
for(int i=0;i<nums.size();i++)
{
if(vis[i]==1 || (i>0 && nums[i]==nums[i-1] && vis[i-1]==0))//如果插入过了或者这个数字不是重复数字序列未插入过的第一个
continue;
singleArray.push_back(nums[i]); //***************
vis[i] = 1; //
dfs(now+1,nums,singleArray); // A
vis[i] = 0; //
singleArray.pop_back(); //***************
}
}
vector<vector<int>> permuteUnique(vector<int>& nums) {
sort(nums.begin(),nums.end());
vis.resize(nums.size());
vector<int> singleArray;
dfs(0,nums,singleArray);
return ans;
}
};