解题思路:
- 排序:首先,我们要把数字数组按从小到大的顺序排好。这样可以帮助我们在寻找不同排列的时候,更容易发现重复的情况。
- 递归:然后,我们使用一种叫做“递归”的方法来帮助我们找到所有的排列。就像搭积木一样,我们一步一步地把数字放进去,直到所有的位置都填满了。
- 记录已使用的数字:为了避免重复使用同一个位置上的数字,我们需要记住哪些数字已经被放在排列里了。
- 跳过重复的数字:如果当前要放置的位置上,出现了和前面位置上一样的数字,而且前面的位置还没有被使用过,那么我们就跳过这个数字,因为这样做可以避免产生重复的排列。
示例代码:
让我们写一段简单的 Java 代码来实现这个想法:
import java.util.ArrayList;
public class Solution {
// 方法名改为permuteUnique,并且返回类型为ArrayList<ArrayList<Integer>>
public ArrayList<ArrayList<Integer>> permuteUnique(int[] numbers) {
ArrayList<ArrayList<Integer>> allPermutations = new ArrayList<>();
// 首先对数组进行排序
Arrays.sort(numbers);
// 创建一个标记数组,用来记住哪些数字已经被使用了
boolean[] used = new boolean[numbers.length];
// 调用递归函数开始构建排列
backtrack(allPermutations, new ArrayList<>(), numbers, used);
return allPermutations;
}
// 递归函数
private void backtrack(ArrayList<ArrayList<Integer>> allPermutations,
ArrayList<Integer> currentPermutation,
int[] numbers,
boolean[] used) {
// 如果当前排列的长度等于数字的数量,说明已经完成了一个排列
if (currentPermutation.size() == numbers.length) {
allPermutations.add(new ArrayList<>(currentPermutation));
} else {
// 遍历每一个数字
for (int i = 0; i < numbers.length; i++) {
// 如果这个数字已经被使用过了,就跳过
if (used[i]) continue;
// 如果当前数字和前一个数字相同,并且前一个数字还没被使用,也跳过
if (i > 0 && numbers[i] == numbers[i - 1] && !used[i - 1]) continue;
// 把当前数字加入到当前排列中
currentPermutation.add(numbers[i]);
// 标记这个数字已经被使用过了
used[i] = true;
// 递归调用自己,继续构建下一个数字的排列
backtrack(allPermutations, currentPermutation, numbers, used);
// 回溯:移除当前数字,准备下一次循环
currentPermutation.remove(currentPermutation.size() - 1);
used[i] = false;
}
}
}
}
如果这篇文章对你有帮助,请点个免费的赞👍,让它能够帮助更多的人。

京公网安备 11010502036488号