您的位置:首页 > 其它

Leetcode47 Permutations II

2015-08-08 01:41 316 查看

Permutations II

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].

Solution1

回溯法解决,但是要注意本轮循环要跳过已经使用过的重复的数字。

import java.util.List;
import java.util.ArrayList;
import java.util.HashSet;
public class Solution {
public List<List<Integer>> permuteUnique(int[] nums) {
List<List<Integer>> result = new ArrayList<List<Integer>>();
if(nums.length==0) return result;
List<Integer> temp = new ArrayList<Integer>();
HashSet<Integer> used = new HashSet<Integer>();
help(nums,used,temp,result);
return result;
}
public void help(int[] nums,HashSet<Integer> used,List<Integer>temp,List<List<Integer>>result){
if(temp.size()==nums.length){
result.add(temp);
return;
}
HashSet<Integer> duplicate = new HashSet<Integer>();
for(int i=0;i<nums.length;i++){
if(used.contains(i)) continue;//如果这个位置上的数已经被用过了,则往下再搜寻
if(duplicate.contains(nums[i])) continue;//重复的数,在本次位置上不能再使用
HashSet<Integer> usedTemp = new HashSet<Integer>(used);
usedTemp.add(i);//这里是存储下标
duplicate.add(nums[i]);//这里是存储数值
List<Integer> temp1 = new ArrayList<Integer>(temp);
temp1.add(nums[i]);
help(nums,usedTemp,temp1,result);
}
}
}


Solution2

另一种类型的回溯。

public class Solution {
public List<List<Integer>> permuteUnique(int[] nums) {
List<List<Integer>> result = new ArrayList<List<Integer>>();
//Arrays.sort(nums);
permuteUnique2(nums,0,result);
return result;
}
public void permuteUnique2(int[] nums,int start,List<List<Integer>> result){
if(start>=nums.length){
List<Integer> item = new ArrayList<Integer>();
for(int num:nums) item.add(num);
result.add(item);
return;
}
HashSet<Integer> used = new HashSet<Integer>();
for(int i=start;i<nums.length;i++){
if(used.contains(nums[i])) continue;
int temp = nums[i];
nums[i] = nums[start];
nums[start] = temp;
used.add(nums[start]);
permuteUnique2(nums,start+1,result);
nums[start] = nums[i];
nums[i] = temp;
}
}
}


Solution3

Leetcode46 Permutations中的解法4一样,这里仍然可以用插入法来求解,但是要复杂得多。这里插入数的时候不是以单个数为单位,而是以所有重复的数字为单位。

public class Solution {
public List<List<Integer>> permuteUnique(int[] nums) {
List<List<Integer>> result = new ArrayList<List<Integer>>();
result.add(new ArrayList<Integer>());
Arrays.sort(nums);
for(int i=0;i<nums.length;i++){
int count = 1;
for(;i+1<nums.length&&nums[i+1]==nums[i];i++,count++);//统计重复的数字个数
int size = result.size();
for(int j=0;j<size;j++) insert(result.get(j),count,nums[i],result);
while(size-->0) result.remove(0);
}
return result;
}
public void insert(List<Integer> item,int count,int num,List<List<Integer>> result){//将重复的数字插入已有的结果中
Stack<Integer> stack = new Stack<Integer>();
while(true){
for(int index=stack.empty()?0:stack.peek()+1;count>0;index++,count--){//插入
stack.push(index);
item.add(index,num);
}
result.add(new ArrayList<Integer>(item));
int i = stack.pop();
item.remove(i);
count++;
for(;i==item.size();count++){//回溯
if(stack.empty()) return;
i = stack.pop();
item.remove(i);
}
stack.push(i+1);//回溯成功后往后挪一个位置再插入
item.add(i+1,num);
count--;
}
}
}


思路较复杂,不推荐此算法。

Solution4

这里借鉴 Leetcode31 Next Permutation的思路来求解本题。

public class Solution {
public List<List<Integer>> permuteUnique(int[] nums) {
List<List<Integer>> result = new ArrayList<List<Integer>>();
Arrays.sort(nums);
while(true){
List<Integer> item = new ArrayList<Integer>();
for(int num:nums) item.add(num);
result.add(item);
int i,j;
for(i=nums.length-1;i>0;i--) if(nums[i-1]<nums[i]) break;
if(i<=0) break;
for(j=nums.length-1;j>0;j--) if(nums[j]>nums[i-1]) break;
int temp = nums[j];
nums[j] = nums[i-1];
nums[i-1] = temp;
for(j = nums.length-1;i<j;i++,j--){
temp = nums[j];
nums[j] = nums[i];
nums[i] = temp;
}
}
return result;
}
}


思路清晰易懂,并且还复用性还非常高。不管是有重复数字还是没有重复数字都可以用这种方法求解。所以比回溯法更值得推荐。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  leetcode