给定一个可包含重复数字的序列,返回所有不重复的全排列。
示例:
输入: [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(list, new ArrayList<>(), nums);
4 return list;
5}
6
7private void backtrack(List<List<Integer>> list, List<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}