枚举系列 生成1~n的排列 java版

本文介绍了一种递归算法,用于生成整数n的所有可能排列,并按字典序输出。通过对不同数字开头的情况进行递归调用,实现了有序排列的生成。此外,还讨论了如何对已知数组进行全排列。

输入整数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);
                        }
                    }
                }
            }
        }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小鹏AI

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值