[LeetCode]Next Permutation

Question:

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


本题难度medium。

算法1:

【复杂度】
时间O(N) 空间O(1)

【思路】
从后往前搜索第一个升序对。比如:1452321,最右边的升序对就是23。为什么是最右边这个?因为题目要求是“next greater”,所以尽量动低位。我将可能的情况列举出来:

一直升序:1  23->1  32
一直降序:3  21->1  23
先降后升:321  45->321  54
没变化:1111->不处理

以上的情况处理都很简单,我将要处理的部分都用空格区分开来了。可以看到,仅仅是将最右边的升序对进行swap(或整体升序处理)即可。最麻烦的情况就是:

先升后降:2  13  21
如果 13 swap,得到 2  31  21却不是next greater。
正确的办法是将 3  21进行升序排列,选一个刚好比1大的数与 1 swap即可,得到 2  21  13

【附】
将各种case考虑清楚即可解题。

【代码】

public class Solution {
    public void nextPermutation(int[] nums) {
        //require
        if(nums==null)
            return;
        int size=nums.length;
        if(size<2)
            return;
        int up_p=-1;    //save the ascending pair index
        //invariant
        for(int i=size-1;i>0;i--){
            if(nums[i-1]<nums[i]){
                up_p=i-1;
                break;
            }
        }
        if(up_p==-1)
            Arrays.sort(nums);
        else{
            if(up_p+1==size-1){
                //swap
                int temp=nums[up_p];
                nums[up_p]=nums[up_p+1];
                nums[up_p+1]=temp;
            }else{
                //sort
                Arrays.sort(nums,up_p+1,size);
                for(int i=up_p+1;i<size;i++)
                    if(nums[i]>nums[up_p]){
                        //swap
                        int temp=nums[up_p];
                        nums[up_p]=nums[i];
                        nums[i]=temp;
                        return;
                    }
            }
        }
    }

}

【follow up】
应该有更快的算法,先留白待续。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值