给定一个可包含重复数字的序列,返回所有不重复的全排列。

示例:

输入: [1,1,2]输出:[
  [1,1,2],
  [1,2,1],
  [2,1,1]
]

上期的问题是:114,全排列

 1public List<List<Integer>> permute(int[] nums) {
2    List<List<Integer>> list = new ArrayList<>();
3    backtrack(listnew ArrayList<>(), nums);
4    return list;
5}
6
7private void backtrack(List<List<Integer>> listList<Integer> tempList, int[] nums) {
8    if (tempList.size() == nums.length) {
9        list.add(new ArrayList<>(tempList));
10    } else {
11        for (int i = 0; i < nums.length; i++) {
12            if (tempList.contains(nums[i])) continue;
13            tempList.add(nums[i]);
14            backtrack(list, tempList, nums);
15            tempList.remove(tempList.size() - 1);
16        }
17    }
18}

解析:

这里比较难理解的就是递归,并且出现在了for循环中,如果对递归比较熟练的话,这里就很好理解了。我们知道递归都有终止条件,这里递归的终止条件是tempList的长度正好等于nums的长度,递归遇到终止条件之后然后开始回退,这里回退的时候还会把最有一个元素给移除掉,然后在for循环的时候把下一个元素再重新加入。

我们还可以换另一种思路来解决,就是通过不断打乱数组的顺序,这个可能更好理解一些

 1public List<List<Integer>> permute(int[] nums) {
2    List<List<Integer>> result = new ArrayList<>();
3    permuteRecursive(nums, 0, result);
4    return result;
5}
6
7void permuteRecursive(int[] nums, int begin, List<List<Integer>> result) {
8    if (begin >= nums.length) {
9        List<Integer> list = Arrays.stream(nums).boxed().collect(Collectors.toList());
10        result.add(list);
11        return;
12    }
13    for (int i = begin; i < nums.length; i++) {
14        swap(nums, begin, i);
15        permuteRecursive(nums, begin + 1, result);
16        swap(nums, begin, i);
17    }
18}
19
20public void swap(int[] A, int i, int j) {
21    if (i != j) {
22        A[i] ^= A[j];
23        A[j] ^= A[i];
24        A[i] ^= A[j];
25    }
26}