❗❗❗必看:
下列题我全部都使用 Java 语言写的,并且均可以提交成功,获得Accepted 结果的. 如果代码和详解看了之后,对答案有任何疑问,都可以在评论区提出来,我都会一个一个回答.
❗❗❗感谢大家的支持,如果喜欢我的博客,关注 点赞 收藏 评论一波,非常感谢!!!
题目 : 全排列
对于数组[1, 2, 3],他们按照从小到大的全排列是
1 2 3
1 3 2
2 1 3
2 3 1
3 1 2
3 2 1
现在给你一个正整数n,n小于8,输出数组[1, 2, …,n]的从小到大的全排列。
Input
输入有多行,每行一个整数。当输入0时结束输入。
Output
对于每组输入,输出该组的全排列。每一行是一种可能的排列,共n个整数,每个整数用一个空格隔开,每行末尾没有空格。
样例测试
输入
2
3
0
输出
1 2
2 1
1 2 3
1 3 2
2 1 3
2 3 1
3 1 2
3 2 1
代码
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Scanner;
//全排列
public class Main {
public static void main(String[] args) {
//输入
Scanner scanner = new Scanner(System.in);
List<Integer> inputs = new ArrayList<>();
//把输入的待求全排列的数据全部都填充到inputs顺序表中,目的是后续方便管理,因为我们要对这些输入的数据进行遍历
while(scanner.hasNextInt()) {
int n = scanner.nextInt();
if(n!=0) {
inputs.add(n);
}else {
break;
}
}
//遍历输入的待求全排列的数据,并把其初始化
for(int n:inputs) {
int[] array = new int[n];
for(int i = 0;i<n;i++) {
array[i] = i+1;
}
//然后把当前生成的array数组存到我们的新顺序表,准备这个是用来保存我们的结果的数组
List<List<Integer>> result = new ArrayList<>();
generatePermutations(array, 0, result);
//字典顺序排序
Collections.sort(result, (a, b) -> {
for (int i = 0; i < a.size(); i++) {
if (!a.get(i).equals(b.get(i))) {
return a.get(i) - b.get(i);
}
}
return 0;
});
// 输出结果
for (List<Integer> permutation : result) {
for (int i = 0; i < permutation.size(); i++) {
System.out.print(permutation.get(i));
if (i < permutation.size() - 1) {
System.out.print(" ");
}
}
System.out.println();
}
}
scanner.close();
}
//递归函数
public static void generatePermutations(int[] array, int start, List<List<Integer>> result) {
if (start == array.length - 1) {
// 当 start 达到数组的最后一个位置时,说明当前排列已经完成
List<Integer> permutation = new ArrayList<>();
for (int num : array) {
permutation.add(num);
}
result.add(permutation); // 将当前排列添加到结果列表中
} else {
// 对 start 及其后的每个位置进行排列
for (int i = start; i < array.length; i++) {
swap(array, start, i); // 交换当前元素和 start 位置的元素
generatePermutations(array, start + 1, result); // 递归生成子排列
swap(array, start, i); // 复原数组
}
}
}
//交换数组中的两个元素
public static void swap(int[] array, int i, int j) {
int temp = array[i];
array[i] = array[j];
array[j] = temp;
}
}
初步思路
利用递归生成数组的全排列,并使用交换元素的方法逐步生成所有排列。
具体步骤
-
输入处理:
- 使用 Scanner 读取多行输入,每行一个整数。
- 将每个输入整数 n 存入列表 inputs 中,直到遇到0为止。
-
初始化数组:
- 遍历 inputs 列表,对于每个 n,初始化一个数组 array,其中包含 [1, 2, …, n]。
-
递归生成全排列:
- 调用 generatePermutations 方法,递归生成数组的全排列。
- 在每次递归调用中,固定一个元素,然后对剩余元素进行全排列。
-
交换元素:
- 使用 swap 方法交换数组中的两个元素,这样可以固定一个元素,然后递归生成其余元素的全排列。
-
恢复数组状态:
- 在递归调用后,将数组恢复原状,以便进行下一次排列的生成。
-
字典序排序:
- 使用 Collections.sort 方法对结果列表 result 按字典序排序。
- 自定义比较器逐元素比较排列中的数字,保证按字典序排列。
-
输出结果:
- 遍历 result 列表,按格式输出每个排列。
总结方法
- 递归与回溯:通过递归生成全排列,并在每次递归后恢复数组状态,实现回溯。
- 字典序排序:通过逐元素比较排列中的数字,确保输出的全排列按字典序排列。
- 元素交换:使用元素交换方法固定部分排列,递归生成其余排列。