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], [2,1,1] ]
----------------------------------------------------------------------------------------------------
不熟悉permutations的朋友可以先看看我前面的博文。
带有重复数的排列将在之前没有重复数的排列的基础上进行改动。
我们设置一个bool数组来标记数是否被使用,
且对原始的array进行排序。
我们看看这两者的差距是什么呢?
如果忽略重复:一开始,isUsed都是false, 可以选择1, 1, 2
如果考虑重复:一开始,即使isUsed都是false, 我们只能选择1,2
所以什么时候,1不能选择了呢?
在选择到第二个1的时候,它的值跟前面的值是一样的。且前面1的isUsed 为false。
(前面的1 isUsed为false,意味着以1开始的,已经回溯过一轮了,所以我们没有必须再对第二个1进行回溯;如果它的isUsed为true,意味着它在前一阶段被使用,所以当前阶段使用是ok的)
总之:同一个阶段,不允许,也没必要对 相同的数,进行递归回溯。
运行时间:
代码:
public List<List<Integer>> permuteUnique(int[] nums) {
Arrays.sort(nums);
List<List<Integer>> result = new ArrayList<>();
List<Integer> store = new ArrayList<>();
boolean[] isUsed = new boolean[nums.length];
doPermute(nums, isUsed, store, result);
return result;
}
private void doPermute(int[] nums, boolean[] isUsed, List<Integer> store, List<List<Integer>> result) {
if (store.size() == nums.length) {
result.add(new ArrayList<>(store));
return;
}
for (int i = 0; i < nums.length; i++) {
if (isUsed[i]) {
continue;
}
if (i > 0 && nums[i] == nums[i - 1] && !isUsed[i - 1]) {
continue;
}
store.add(nums[i]);
isUsed[i] = true;
doPermute(nums, isUsed, store, result);
store.remove(store.size() - 1);
isUsed[i] = false;
}
}