题目:47
题意:给定一个含有重复元素的数组,求出这个数组的全排列,并且使得任意排列不重复
题解:回溯
主体思想,和原题目46全排列类似,使用回溯算法,主要考虑两个子过程:
- 递归出口:n(已经选择的数组中的元素个数) == len(数组长度)当已经选择的数组中的元素中的个数等于数组的大小就得到了一个排列
- 递归过程:n < len 如何选择下一个元素,下一个元素不能是之前已经选择过的,所以我们采用一个标记数组,标记数组中已经访问过的元素。
目前这个过程和46题还是完全一致的,得到的结果会包含大量重复的数组,所以我们需要去除重复,我们自然想到可以先对数组排序,这样方便对相同元素进行处理,接下来,我们只需要保证在选择第i个数字的时候,重复数字只会被填入一次即可,即下面代码中的判断是否重复哪一行所表示的
class Solution {
public:
vector<vector<int>> permuteUnique(vector<int>& nums) {
vector<vector<int> > ans;
sort(nums.begin(), nums.end());
int len = nums.size();
vector<int> flag(len, 0); //标记数组
vector<int> v;
backtracking(ans, v, flag, nums, len);
return ans;
}
void backtracking(vector<vector<int> >& ans, vector<int>& v,vector<int>& flag, vector<int>& nums, int n){
if(n == 0){
ans.push_back(v);
return;
}
for(int i = 0; i < nums.size(); ++i){
if(i > 0 && flag[i-1] == 0 && nums[i-1] == nums[i]) //判断是否重复关键步骤
continue;
if(flag[i] == 0){
v.push_back(nums[i]);
flag[i] = 1;
backtracking(ans, v, flag, nums, n-1);
flag[i] = 0;
v.pop_back();
}
}
return;
}
};