输入整数n,按字典序从小到大的顺序输出前n个数的所有排列。
两个序列的字典序大小关系等价于从头开始第一个不相同位置处的大小关系。
例如,(1,3,2)<(2,1,3),字典序最小的排列是(1,2,3,4,…,n),最大的排列是(n,n-1,n-2,…,1)。
n=3时,所有排列的排序结果是:(1,2,3)、(1,3,2)、(2,1,3)、(2,3,1)、(3,1,2)、(3,2,1)
分析:
对此问题用递归的思想解决:先输出所有以1开头的排列(递归调用),
然后输出以2开头的排列(递归调用),接着以3开头的排列,…,最后才是以n开头的排列。
以1开头的排列的特点是:第一位是1,后面是按字典序的2~9的排列。
所以在设计递归函数需要以下参数:
(1)已经确定的“前缀”序列,以便输出;(递归的出口)
(2)需要进行全排列的元素集合,以便依次选做第一个元素
核心代码:
private static void print_permutation(int n, int[] result, int cur) {
if (cur == n) { // 递归边界,递归出口
for (int i = 0; i < result.length; i++) {
System.out.print(result[i] + " ");
}
System.out.println();
}
else
{
for(int i = 1; i <= n; i++){ // 尝试在result[j]中填入各种整数i(1~n)
boolean flag = true;
for (int j = 0; j < cur; j++) {
if (result[j] == i) { // 如果i已经在result[0]~result[j-1]出现过 则不能再选
flag = false;
}
}
if (flag) {
result[cur] = i;
print_permutation(n, result, cur + 1);
}
}
}
}
如果把问题改成:输入数组Result,并按字典序输出数组Result各元素的所有全排列。
分析:
需要对上述递归函数print_permutation修改
把辅助数组Array加到print_permutation的参数列表中
然后把代码中的
if(Result[j]==i) 和 Result[cur]=i
分别改成
if(Array[j]==Result [i]) 和 Array[cur]=Result [i]
只有把Result的所有元素按从小到大的顺序排序
然后调用print_permutation(n,Array, Result,0)即可
核心代码:
private static void print_permutation(int n, int[] array, int[] result,int cur) {
if (n == cur) {//递归出口
for(int i = 0; i < result.length; i++){
System.out.print(result[i] + " ");
}
System.out.println();
} else {
for (int i = 0; i < n; i++) {//i为array数组下标
int c1 = 0;//统计result数组中已经插入多少个array[i]
int c2 = 0;//统计array数组中已经插入多少个array[i]
if ( i==0 || array[i] != array[i - 1]) {//如果当前字符和前一个字符相同,则跳过该字符.避免重复计算。
for (int j = 0; j < cur; j++) {//result中已有array[i]的个数
if (result[j] == array[i]) {
c1++;
}
}
for (int j = 0; j < n; j++) {
if (array[j] == array[i]) {//扫描array中已有array[i]的个数
c2++;
}
}
if (c1 < c2) {
result[cur] = array[i];
print_permutation(n, array, result, cur + 1);
}
}
}
}
}
本文介绍了一种递归算法,用于生成整数n的所有可能排列,并按字典序输出。通过对不同数字开头的情况进行递归调用,实现了有序排列的生成。此外,还讨论了如何对已知数组进行全排列。
501

被折叠的 条评论
为什么被折叠?



