Next Permutation

问题描述

Implement next permutation, which rearranges numbers into the lexicographically next greater permutation of numbers.

If such arrangement is not possible, it must rearrange it as the lowest possible order (ie, sorted in ascending order).

The replacement must be in-place, do not allocate extra memory.

Here are some examples. Inputs are in the left-hand column and its corresponding outputs are in the right-hand column.
1,2,3 → 1,3,2
3,2,1 → 1,2,3
1,1,5 → 1,5,1

思考:如何反转,替换才能达到目的

想法:

  • 1、从后往前,找出num[i] < num[i + 1]的i,然后,在(i + 1 , num.length - 1)中找出num[i]应该插入的位置j(即保证从i + 1 到 num.length - 1,序列为逆序,且num[j] > num[i]>num[j+1]),调换num[i] 和num[j]的值.(找j的过程可以用二分查找)
  • 2、对i + 1到num.length的序列逆序(先逆序再调换顺序也一样,)

代码:

没有二分查找,且先替换,再逆序

/**
 * Created by Risky on 2015/4/20.
 */
public class Solution {
    public void nextPermutation(int[] num) {
        int len = num.length;        
        if(len < 2)
            return;       
        int index1 = len - 2;
        while(index1 >= 0 && num[index1] >= num[index1 + 1])
            index1--;
        int index2 = index1 + 1;       
        while(index1 >=0 && index2 < len && num[index2] > num[index1] )
            index2++;
        if(index1 >= 0 && index2 <= len)
            swap(num,index1,index2 - 1);
        reverse(num,index1 + 1,len - 1);
    }

    private void swap(int[] num, int i, int j){
        int temp = num[i];
        num[i] = num[j];
        num[j] = temp;
    }

    private void reverse(int [] num, int start, int end){
        if(start == end)
            return;
        int mid = (start + end) >> 1;
        for(int i = start; i <= mid; i++)
            swap(num,i,end + start - i);
    }
}

带二分查找,先逆序,再替换

/**
 * Created by Risky on 2015/4/20.
 */
public class Solution {
    public void nextPermutation(int[] num) {
        int len = num.length;
        if(len < 2)
            return;
        int index1 = len - 2;
        while(index1 >= 0 && num[index1] >= num[index1 + 1])
            index1--;
        reverse(num,index1 + 1,len - 1);
        if(index1 ==  -1)
            return;
        int index2 =  find(num,index1 + 1,len - 1, num[index1]);
        if(index2 <= len)
            swap(num,index1,index2);


    }

    public int find(int[] num, int start, int end, int target) {
        while(start < end){
            int mid = (start + end) >> 1;
            if(target >= num[mid])
                start= mid + 1;
            else
              end = mid;
        }
        return   start;
    }

    private void swap(int[] num, int i, int j){
        int temp = num[i];
        num[i] = num[j];
        num[j] = temp;
    }

    private void reverse(int [] num, int start, int end){
        if(start == end)
            return;
        int mid = (start + end) >> 1;
        for(int i = start; i <= mid; i++)
            swap(num,i,end + start - i);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值