[ LeetCode ] #31. Next Permutation(下一个排列数 C++ & Python)

题目:31. 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 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,3 → 1,3,2
3,2,1 → 1,2,3
1,1,5 → 1,5,1

题意:

给一个数列,从左到右按照高位到低位当作一个整数(num),返回一个由相同数字不同组合比 num 的数。要求返回的结果是大于num且与num最为相近的数,如果不存在(即 数列的数是降序排列的),那么将数列按升序排列后输出。

分析:

使用所给列表的元素,从左到右按照有高到低位的顺序组成为一个整数(假设为num),需要求得比num大的新组合newNum,同时还要求newNum - num的值最小,所以 只有当尽可能确保两数的高位部分相等时,两数间的差才会较小。实现思路如下:

  • 首先,使用imin标记为最后一位元素的下标。
  • 从倒数第二位元素开始向前遍历,查找最右边的相邻两个元素且为左小右大的位置,如果找到把imin替换为较小元素的下标,并且终止循环(这里是因为,当发现最最右端出现高位的数字比低位的数字小时,此时可以保证最多的高位数对应相等,因为 可以把第一个符合条件的元素位置当作需要替换为较大值的位置)。
  • 如果第二步的循环执行完毕,且imin仍然为最后一位元素的下标时,即可将数列按升序排列,并返回结果。因为只有所有的相邻元素均为左边大于右边时,此时可以说明原列表元素是降序排列的,因此不存在本题所要求的解。
  • 找到最右边需要替换的位置之后。接下来需要找使用哪个数替换产生的数值会比原来的大,且两个数相距较近。因为高位元素保持不变了,所以接下来只需要在上面求得的imin位置后面查到到一个大于它但与它又是最仅的元素位置,进行替换即可。(这里取imin右边最小的大于imin位置的元素,是因为 如果仅是大于imin位置的元素,那么可能会产生不是最接近原数值的结果)。
  • 相应位置的元素替换之后,此时数列中[0,imin]之间组成的数,已经比原来的数值要大了,因为imin相对后面的数为最高位,所以当求与原数值最接近的结果时,现在只需要保证imin后的元素所构成的数值最下即可,又因 升序排列所构成的数值一定最小,因此这里直接升序排列imin后面的元素即可。
  • 返回结果。实现如下

Code & C++

class Solution {
public:
    void nextPermutation(vector<int>& nums) {
        int imin = nums.size()-1;
        for(int i=nums.size()-2; i>=0; --i){
            if(nums[i]<nums[i+1]){
                imin = i;
                break;
            }
        }
        if(imin == nums.size()-1){
            return sort(nums.begin(), nums.end());
        }
        int maxnum = numeric_limits<int>::max(), idx=-1;
        for(int i=nums.size()-1;i>imin;--i){
            if(nums[i] > nums[imin] && nums[i]<maxnum ){
                    maxnum = nums[i];
                    idx = i;
            }
        }
        swap(nums[imin], nums[idx]);
        sort(nums.begin()+imin+1,nums.end());
    }
};

Result:

Runtime: 12 ms, faster than 100.00% of C++ online submissions for Next Permutation.

Memory Usage: 10.2 MB, less than 24.63% of C++ online submissions for Next Permutation.

Code & Python

class Solution:
    def nextPermutation(self, nums: List[int]) -> None:
        """
        Do not return anything, modify nums in-place instead.
        """
        i = len(nums)-1
        while i>0 and nums[i] <= nums[i-1]:
            i-=1
        if i == 0:
            nums.sort()
        else:
            i , j , maxnum , idx=i-1, len(nums)-1, 1<<31, -1
            while i<j:
                if nums[j] > nums[i] and nums[j] < maxnum:
                    maxnum, idx = nums[j], j
                j-=1
            nums[i], nums[idx] = nums[idx], nums[i]
            nums[i+1:] = sorted(nums[i+1:])

Result

Runtime: 48 ms, faster than 65.63% of Python3 online submissions for Next Permutation.

Memory Usage: 13.3 MB, less than 5.24% of Python3 online submissions for Next Permutation.

 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值