题目描述
给定一个可包含重复数字的序列,返回所有不重复的全排列。
样例
输入: [1,1,2]
输出:
[
[1,1,2],
[1,2,1],
[2,1,1]
]
算法
(DFS+回溯)
-
以
[1,1,2]
为例,图解如下
-
这题剪枝的前提需要先排序,排序后所有相等的数全部都靠在一起
- 碰到重复元素会有两种情况
1.这个数正在被使用,那么下一个位置能够摆上相同的数字
2.这个数刚刚被撤销,如果下一个位置摆上刚才撤销回来的数字,那么递归树必然和撤销前的递归树重复,所以应该剪枝
时间复杂度:$O(n*n!)$
Java 代码
class Solution {
int n;
boolean[] v;
List<Integer> list = new ArrayList();
List<List<Integer>> res = new ArrayList<>();
public List<List<Integer>> permuteUnique(int[] nums) {
n = nums.length;
if (nums == null || n == 0) return new ArrayList<>();
v = new boolean[n];
Arrays.sort(nums);
dfs(nums, 0);
return res;
}
private void dfs(int[] nums, int index) {
if (index == n) {
res.add(new ArrayList<>(list));
return;
}
for (int i = 0; i < n; i++) {
if (i > 0 && nums[i - 1] == nums[i] && !v[i - 1]) continue;
if (!v[i]) {
v[i] = true;
list.add(nums[i]);
dfs(nums, index + 1);
v[i] = false;
list.remove(list.size() - 1);
}
}
}
}