您的位置:首页 > 其它

[LeetCode]Permutations II(!!!!!DFS递归&&回溯)

2015-07-19 15:26 453 查看
Given a collection of numbers that might contain duplicates, return

all possible unique permutations.

For example, [1,1,2] have the following unique permutations:

[1,1,2], [1,2,1], and [2,1,1].

生成给定数字的全排列,这里给定数字中有重复数字,所以在相邻的重复数字中,我们只递归第一个遇到的未访问的数字。

可以以11112为例

下标为01234

第0层递归为1

第一层时再传1 ,一直递归直至11112出现

在第一层递归传nums[2],这是nums[1]未访问,所以nums[2]被跳过,接着num[3]也被跳过,传入nums[4],直至12111出现

class Solution {
public:
vector<vector<int>> permuteUnique(vector<int>& nums) {
sort(nums.begin(),nums.end());
vector<vector<int>> permus;
if(nums.size()<1)   return permus;
vector<bool> visited(nums.size(),false);    //初始都未访问过
vector<int> curr;
permu_all(permus,visited,curr,nums);
return permus;
}
void permu_all(vector<vector<int>>& permus, vector<bool>& visited, vector<int> curr, vector<int>& nums){
if(curr.size()==nums.size()){
permus.push_back(curr);
return;
}

for(int i = 0; i < nums.size(); ++i){
if(i>0&&nums[i]==nums[i-1]&&!visited[i-1]) continue;
if(visited[i]==false){
visited[i] = true;
curr.push_back(nums[i]);
permu_all(permus, visited, curr, nums);
curr.pop_back();
visited[i]=false;
}
}
}
};


实际上这种处理方式更容易理解

对于当前permutation,后面这这个元素相同的元素我们都可以pass掉,就是说在递归的出口处处理

class Solution {
public:
vector<vector<int>> permuteUnique(vector<int>& nums) {
sort(nums.begin(),nums.end());
vector<vector<int>> permus;
if(nums.size()<1)   return permus;
vector<bool> visited(nums.size(),false);    //初始都未访问过
vector<int> curr;
permu_all(permus,visited,curr,nums);
return permus;
}
void permu_all(vector<vector<int>>& permus, vector<bool>& visited, vector<int> curr, vector<int>& nums){
if(curr.size()==nums.size()){
permus.push_back(curr);
return;
}

for(int i = 0; i < nums.size(); ++i){
//if(i>0&&nums[i]==nums[i-1]&&!visited[i-1]) continue;
if(visited[i]==false){
visited[i] = true;
curr.push_back(nums[i]);
permu_all(permus, visited, curr, nums);
curr.pop_back();
visited[i]=false;
while(i<nums.size()&&nums[i]==nums[i+1])    ++i;
}
}
}
};


两种情况AC都是40ms

另外一种思路是利用Next permutations的思路初始的是最小的数,然后每次寻找它的next permutation

寻找的思路,

以1243为例,先后往前找第一个非递增的数,这里找到nums[1]=2,如果找到为nums[-1]则结束。否则再从后往前找第一个比2大的数,这里为nums[3]=3。交换nums[1]和nums[3],变成1342,从下标为2开始翻转后面的数变成1324

class Solution {
public:
vector<vector<int>> permuteUnique(vector<int>& nums) {
sort(nums.begin(),nums.end());
vector<vector<int>> permus(1,nums);
int i,j;
while(1){
for(i = nums.size()-1; i >0; --i){     //和i前面的数比
if(nums[i]>nums[i-1])
break;                          //第一个非升序的数
}
if(i==0)  break;          //找到最大的数了

for(j = nums.size()-1; j>=i; --j){
if(nums[j]>nums[i-1])
break;
}
swap(nums[i-1],nums[j]);
reverse(nums.begin()+i,nums.end());
//reverse(nums,i);
permus.push_back(nums);
}
return permus;

}
void swap(int &a, int &b){
a=a^b;
b=a^b;
a=a^b;

}
/*
void reverse(vector<int> &v, int index){
int l =index;
int r = v.size()-1;
while(l<r){
swap(v[l++],v[r--]);
}
}*/
};
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: