1.根据全排列,标记已选元素下标,最后利用set去重
class Solution {
public List<List<Integer>> permuteUnique(int[] nums) {
Set<List<Integer>> set = new HashSet<>();
int n = nums.length;
backtrack2(n, nums, new ArrayList<>(), set, new ArrayList<>());
return new ArrayList<>(set);
}
private void backtrack2(int n, int[] nums, List<Integer> currentPerm, Set<List<Integer>> set, List<Integer> li) {
// 递归结束条件:当currentPerm的长度等于nums的长度时,已经得到一个全排列
if (currentPerm.size() == n) {
set.add(new ArrayList<>(currentPerm));
//li = new ArrayList<>();
return;
}
for (int i = 0; i < n; i++) {
if (li.contains(i)) {
continue;
}
currentPerm.add(nums[i]);
li.add(i);
backtrack2(n, nums, currentPerm, set, li);
currentPerm.remove(currentPerm.size() - 1);
li.remove(li.size() - 1);
}
}
}
2.先排序 后回溯
public class PermutationsUnique {
public List<List<Integer>> permuteUnique(int[] nums) {
List<List<Integer>> permutations = new ArrayList<>();
Arrays.sort(nums); // 对数组进行排序,确保相同的数字相邻
backtrack(nums, new boolean[nums.length], new ArrayList<>(), permutations);
return permutations;
}
private void backtrack(int[] nums, boolean[] visited, List<Integer> currentPerm, List<List<Integer>> permutations) {
if (currentPerm.size() == nums.length) { // 递归结束条件:当currentPerm的长度等于nums的长度时,已经得到一个全排列
permutations.add(new ArrayList<>(currentPerm));
return;
}
for (int i = 0; i < nums.length; i++) {
if (visited[i] || (i > 0 && nums[i] == nums[i - 1] && !visited[i - 1])) {
continue; // 跳过已经访问过的数字和重复的数字
}
visited[i] = true;
currentPerm.add(nums[i]);
backtrack(nums, visited, currentPerm, permutations);
visited[i] = false;
currentPerm.remove(currentPerm.size() - 1);
}
}