【LeetCode】解题31:Next Permutation

Problem 31: Next Permutation [Medium]

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 and use only constant 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,31,3,2
3,2,11,2,3
1,1,51,5,1

来源:LeetCode

解题思路

下一个更大的排列应该从改变数值后影响最小的位数考虑。

  • 第一层循环中,设置指针i从后往前考察,是否有某一位上的数nums[i],其值可以通过与一个更小位上的数 K K K K ∈ K\in Knums[i+1]~nums[n-1])做交换而变大,并且变大的程度最小,这要求:
    K = min ⁡ ( { n u m s [ j ] ∣ n u m s [ j ] > n u m s [ i ] , j ∈ [ i + 1 , n − 1 ] } ) K = \min(\{nums[j]\mid nums[j]>nums[i],j\in[i+1,n-1]\}) K=min({nums[j]nums[j]>nums[i],j[i+1,n1]})
  • 第二层循环中,由于之前没有找到可以改变数值的位,说明指针i后的数按降序排列,则当从后往前寻找比nums[i]大的数值时,但凡存在这样的数nums[j],都一定是nums[i+1]~nums[n-1]中符合要求的最小数值。
  • 找到可以交换的数nums[j]后,与nums[i]做交换,此时的nums[i+1]~nums[n-1]仍然保持降序排列,只要使用双指针将其改为升序排列,即是符合题意的下一个更大排列。
  • 此外,当排列已经是降序排列时,同样只需用双指针法改为升序排列即可。

两层循环时间复杂度为O(n2),双指针法排序时间复杂度O(n),因此总时间复杂度O(n2)。

要点:双指针

Solution (Java)

class Solution {
    public void nextPermutation(int[] nums) {
        int N = nums.length;
        int temp, l, r;
        for(int i = N-2; i >= 0; i--){
            for(int j = N-1; j > i; j--){
                if(nums[j] > nums[i]){
                    temp = nums[i];
                    nums[i] = nums[j];
                    nums[j] = temp;
                    //sort nums[i+1]~nums[N-1](descending order) in ascending order
                    l = i+1;
                    r = N-1;
                    while(l < r){
                        temp = nums[l];
                        nums[l] = nums[r];
                        nums[r] = temp;
                        l++;
                        r--;
                    }
                    return;
                }
            }
        }
        l = 0;
        r = N-1;
        while(l < r){
            temp = nums[l];
            nums[l] = nums[r];
            nums[r] = temp;
            l++;
            r--;
        }
    }
}

修改过程

  • 一开始的思路是使用指针i从后往前检查,在i之前是否有比nums[i]小的数值nums[j],小就替换,然后将j之后的数从小到大排序。若输入[4,2,0,2,3,2,0],则这种思路输出[4,2,2,0,0,2,3],正确答案应该是[4,2,0,3,0,2,2]。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值