[leetcode]nextPermutation

思路如下:

假设当前给定permutation序列为 a1 a2 a3...an.

  1. 从序列尾部a[n]开始向头部扫描,找到第一个相邻升序序列 a[i-1]< a[i] ; 因为是扫描到的第一个相邻升序,则此时有a[i]>=a[i+1]>=a[i+2]...>=a[n].
  2. 从a[n]逆序遍历至a[i] 找到第一个大于a[i-1]的值a[j] ,交换a[i-1]和a[j].因为a[j]是第一个大于a[i-1]的,所以有a[j+1]至a[n]都小于等于a[i-1]. 即替换后的序列a[1]...a[j],a[i],a[i+1]..a[j-1],a[i-1],a[j+1]...a[n] 有a[i]>=a[i+1]>=a[j-1]>=a[j]>a[i-1]>=a[j+1]...>=a[n].即从i-n的范围仍然是个非升序序列。
  3. 因为我们已经改变a[i-1]的值为其后序列中大于a[i-1]的值中最接近他的。那么剩下的只需将a[i]~a[n]的范围内的值变为升序序列即可。

示例: 3 2 6 5 4 1

我们找到第一个相邻升序序列 2 6 然后找到2的后面第一个大于2的值4 交换。变为 3 4 6 5 2 1 

然后将6 5 2 1变为升序序列,得到最后结果 3 4 1 2 5 6

 

简单说明下正确性吧: 当找到第一个升序序列 2 6,由于是第一个升序序列,所以以6开头的6 5 4 1肯定是非升序的。对于一个非升序的permutation部分,肯定是这部分内最大的了,所以没办法操作他们去获得整个permutation的下一个值,则需要替换前一位2(用后面的大于他的最小值4替换,由于后面部分是递减的,大于他的最小值肯定是从尾往前第一个比他大的)。序列变为 3 4 6 5 2 1,因为4是第一个比他大的,所以1<2.又因为6>5>4>2.所以后面的序列6 5 2 1也是递减的,使用i,j指针 交换为递增的 1 2 5 6 即可。

 

代码

   public void nextPermutation(int[] num) {
        // Start typing your Java solution below
        // DO NOT write main() function
        if(num == null||num.length == 0) return ;
        
        int i = num.length-1;
        for(;i>=1;i--){
            if(num[i]>num[i-1]){
                break;
            }
        }
        int  j = num.length-1;
        int temp;
        if(i>=1){ 
            i = i-1;
            while(num[j]<=num[i]) j--;
            temp = num[i];
            num[i] = num[j];
            num[j] = temp;
            i = i+1;
        }
        j = num.length-1;
        
        while(i<j){
          temp = num[i];
          num[i] = num[j];
          num[j] = temp;
          i++; j--;
        }
        
    }

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值