给定一个可包含重复数字的序列,返回所有不重复的全排列。
示例:
输入: [1,1,2]
输出:
[
[1,1,2],
[1,2,1],
[2,1,1]
]来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/permutations-ii
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
这道题和46题基本一致,不同之处在于结果不能重复。如何避免重复,也就是如何剪枝。在46题中,我们用一个boolen型数组,来记录某个数字是否已经使用,这道题也同样可以使用这种方法。如何使用?首先给数组排序,这是毋庸置疑的,排序之后,值相同的元素就会排列到一起,这就达到了第一个目的,然后dfs,在dfs回退过程中,前一个枝叶一定会被修改为false,那么就可以利用这一点来进行剪枝。下面是代码。在剪枝的条件中,如果不加used[i-1]
这个条件,所得的结果一定是空,因为在这道题中,数组的数字中一定有重复,排序之后,这个条件一定是false,继续continue,就会导致加入combination数组的元素永远比length少,不会加入到ans中。
class Solution {
public List<List<Integer>> permuteUnique(int[] nums) {
List<List<Integer>> ans = new ArrayList<>();
Deque<Integer> combination = new ArrayDeque<>();
int length = nums.length;
int target = 0;
Arrays.sort(nums);
ArrayList array = new ArrayList(Collections.singleton(nums));
boolean[] used = new boolean[length];
if (length == 0) {
return null;
}
dfs(ans, combination, nums, length, used);
return ans;
}
public void dfs(List<List<Integer>> ans, Deque<Integer> combination, int[] nums,
int length,boolean[] used) {
if (combination.size() == length) {
ans.add(new ArrayList<>(combination));
return;
}
for (int i = 0; i < length; i++) {
if (!used[i]) {
if (i > 0 && nums[i] == nums[i - 1] && used[i-1]) {
continue;
} else {
combination.addLast(nums[i]);
used[i] = true;
dfs(ans, combination, nums, length, used);
used[i] = false;
combination.removeLast();
}
}
}
}
}