小学生都能看懂的题解 | #有重复项数字的全排列#
有重复项数字的全排列
https://www.nowcoder.com/practice/a43a2b986ef34843ac4fdd9159b69863
解题思路:
- 排序:首先,我们要把数字数组按从小到大的顺序排好。这样可以帮助我们在寻找不同排列的时候,更容易发现重复的情况。
- 递归:然后,我们使用一种叫做“递归”的方法来帮助我们找到所有的排列。就像搭积木一样,我们一步一步地把数字放进去,直到所有的位置都填满了。
- 记录已使用的数字:为了避免重复使用同一个位置上的数字,我们需要记住哪些数字已经被放在排列里了。
- 跳过重复的数字:如果当前要放置的位置上,出现了和前面位置上一样的数字,而且前面的位置还没有被使用过,那么我们就跳过这个数字,因为这样做可以避免产生重复的排列。
示例代码:
让我们写一段简单的 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; } } } }
如果这篇文章对你有帮助,请点个免费的赞👍,让它能够帮助更多的人。
#题解#小学生都能看懂的算法 文章被收录于专栏
主要面向小白的算法文章。以小学生都能看懂为目标而编写,顺便巩固下自己。