Java 全排列

参考:https://blog.csdn.net/joylnwang/article/details/7064115

回溯

  • 描述

和高中的排列组合有些像,比如{1,2,3}有几种排列方式:
第一个位置有3种,第二个位置有2种,第三个位置有1种,也就是3 * 2 * 1=6种
只不过上面的元素是从集合中拿出的,这里的元素是数组通过和后面的元素交换得到的

  • 代码
  • 这个程序只会递归到倒数第二层,最后一层无需固定(图中的红线是达不到的)
  • 为什么i=n?如果ar[i] = ar[n],无需交换?
    交换是为了遍历每一种情况,这个数组本身的顺序也算一种情况,这次的遍历是为了进入递归,并且会限制最后一层
  • 为什么要swap两次?
    第二次swap是为了让数组保持原样,利于回溯。

在这里插入图片描述

    public static void out(int[] ar,int n){
        if(n==ar.length-1) {
//            输出
            print(ar);
        }
//        n代表第一个未被固定的位,i代表和n交换的数
        for (int i = n; i < ar.length; i++) {
            swap(ar,n,i);
            out(ar,n+1);
            swap(ar,n,i);
        }
    }

辅助函数

  public static void swap(int[] ar , int m,int n){
        int tmp = ar[m];
        ar[m] = ar[n];
        ar[n] = tmp;
    }

    public static void print(int[] ar){
        for(int i:ar){
            System.out.print(i+" ");
        }
        System.out.println();
    }

字典序

  • 描述
  • 类似字符串排序,排列之间可以比较大小,参考字符串比较大小
  • 上面的方法很难拿到指定一个排列的下一个排列(升序),字典序可以更加容易的拿到,并通过不断拿到下一个字符串的方式,得到全排列。这里只给出拿到下一个排列的方法(findNext)
  • 流程-------------------------------------------------------例子 2143
    • 1.从右向左找到相邻下标 a,b,且[a]<[b]-----------------[a]=1,a=1
    • 2.从b…n中寻找大于[a]的最小的数[c]-----------------------[c]=3,c=3
    • 3.交换值-----------------------------------------------------------2341
    • 4.a下标后的数升序排列----------------------------------------2314
    public static int[] findNext(int[] arr){
        if(arr==null||arr.length==0)return null;
        int[] ar = arr.clone();
//        swap1 是a
        int swap1 = -1;
        int len = ar.length;
        for (int i = len-1; i >=1; i--) {
            if(ar[i]>ar[i-1]){
                swap1 = i-1;
                break;
            }
        }
//        swap2 是c
        int swap2 = swap1+1;
        //如果这个就是排列中最大的,返回最小的排列
        if(swap1 == -1) {
            Arrays.sort(ar);
            return ar;
        };
//        找到swap2 
        for (int i = swap1; i < len; i++) {
            int tmp = ar[i];
            if(ar[swap1]<tmp&&tmp<ar[swap2]){
                swap2 = i;
            }
        }
//        交换
        swap(ar,swap1,swap2);
//        a坐标后的数升序
        int first = swap1+1;
        Arrays.sort(ar,first,len);
        return ar;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值