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]
.
解法1:采用将当前元素与后续元素交换,并递归实现的方法
int len;
bool isSwap(vector<int> & nums, int s, int e){//查找重复元素,如果前面已经出现过该元素,最后返回false,不会替换
while(nums[s]!=nums[e]&&s<e) s++;
if(s==e)return true;
else return false;
}
void generate(vector<vector<int>> & ret, vector<int> & nums, int cur){
if(len==cur+1){
ret.push_back(nums);
}
else{
for(int i=cur; i<len; i++){
if(!isSwap(nums, cur, i)) continue;//如果前面出现过该元素,则不执行交换,因为cur元素已经跟前面的元素发生过替换,替换后,在generate(ret, nums, cur+1)已经直接或间接的跟该元素发生过替换,所以不要再次交换
swap(nums[cur], nums[i]);
generate(ret, nums, cur+1);
swap(nums[cur], nums[i]);
}
}
}
vector<vector<int>> permuteUnique(vector<int>& nums) {
vector<vector<int>> ret;
len=nums.size();
sort(nums.begin(), nums.end());//首先对数据序列进行排序,使相同元素挨着
generate(ret, nums, 0);
return ret;
}
解法2.采用字典序的方法,使用非递归排序方法
vector<vector<int>> permuteUnique(vector<int>& nums) {
vector<vector<int>> ret;
if(nums.size()<=0)
return ret;
int len=nums.size();
sort(nums.begin(), nums.end());//首先对数据序列进行排序,是相同元素挨着
ret.push_back(nums);
int min;
int nextMin;
int start;
int end;
while(true){
min=len-2;
nextMin=len-1;
while(min>=0 && nums[min]>=nums[min+1] ) min--;//1. 从后往前找第一个比右边数据小的元素
if(min==-1)
break;
while(nextMin>min && nums[nextMin]<=nums[min])nextMin--;//2. 从后往前找第一个比nums[min]大的数据
swap(nums[nextMin], nums[min]);//3. 交换数据
start=min+1;
end=len-1;
while(start<end){//后面的数据保持从小到大排序
swap(nums[start], nums[end]);
start++;
end--;
}
ret.push_back(nums);
}
return ret;
}
以上两种方法在leetcode的执行时间都是32ms