解法一:回溯
和普通的全排列一样,都可以使用回溯法,唯一的区别在于需要处理重复元素之前位置互换带来的冗余。令重复元素之前保持某种固定的顺序是一种解决冗余的思路。
class Solution {private List<List<Integer>> ans;private boolean[] isVisited;public List<List<Integer>> permuteUnique(int[] nums) {int n = nums.length;ans = new LinkedList<>();isVisited = new boolean[n];// 排序使得重复元素连在一起Arrays.sort(nums);Integer[] arr = new Integer[n];permute(n, nums, 0, arr);return ans;}private void permute(final int N, final int[] nums, int index, Integer[] arr) {if (index == N) {List<Integer> list = new ArrayList(N);Collections.addAll(list, arr);ans.add(list);return;}for (int i = 0; i < N; ++i) {if (isVisited[i]) {continue;}// 对于重复数字, 在全排列中出现的次序必须与原来的顺序保持一致// 因此如果原来排在它前面的重复数字还没有被使用, 它也不能加入全排列if ((i > 0) && (nums[i] == nums[i - 1]) && (!isVisited[i - 1])) {continue;}arr[index] = nums[i];isVisited[i] = true;permute(N, nums, index + 1, arr);isVisited[i] = false;}}}
