LeetCode下一个排列

31. 下一个排列

实现获取 下一个排列 的函数,算法需要将给定数字序列重新排列成字典序中下一个更大的排列(即,组合出下一个更大的整数)。

如果不存在下一个更大的排列,则将数字重新排列成最小的排列(即升序排列)。

必须 原地 修改,只允许使用额外常数空间。

示例 1

输入:nums = [1,2,3]

输出:[1,3,2]

示例 2

输入:nums = [3,2,1]

输出:[1,2,3]

示例 3

输入:nums = [1,1,5]

输出:[1,5,1]

示例 4

输入:nums = [1]

输出:[1]

思路:

这种题你第一次看的时候会一脸懵逼,等你做完,再过几个月又看,还是会一脸懵逼。因为对大多数人来说,本来就不是靠智力和“硬想”来做的,都是靠熟能生巧与套路总结而已。当然有些难题是可以硬想出来的,虽然靠自己做出来是挺爽的,不过那种思路多半毫无章法,代码也乱七八糟的,自己说不定都无法复现。

这也是我总结这些的目的,有些题就算我现在会写,如果不记住结论的话,再做还是不会。

这种“下一个排列、下一个较大值”,请直接记住套路:

  首先,无法进行下一个排列的数组,自然就是从大到小排列的,即整个数组呈“一直下降”趋势。对于这种情况,我们根据题意把它升序排列即可。跟我们的算法无关。

    而对于其他情况,必然会有某一处是有一个“上升”的情况。则操作方法如下:

1.从右往左,找到第一个“上坡”,“上坡”就是指相邻的两个数,左边小于右边。现在可以肯定的是,因为我们是从右向左找的,所以一旦找到“上坡”后,“上坡”的右边界往后肯定全都是“下坡”。

 2.记录下“上坡”的左边界,从右往左,找比上坡左边界大的数,当然这样的数可能会有多个,我们只要找到第一个,就记录下这个值与位置,停止寻找。 这样做的意义是:在“上坡”左边界的右边,找到比左边界大的最小数。 说起来有点绕哈,但这样就可以保证,拿这个找到的数与左边界交换,就是最小交换。

3.把“上坡”左边界右边的部分从小到大排序。

代码:

class Solution(object):

    def nextPermutation(self, nums):

        """

        :type nums: List[int]

        :rtype: None Do not return anything, modify nums in-place instead.

        """

        #先处理特殊情况

        s1 =sorted(nums[:],reverse=True) #将数组从大到小排列,和原数组比较

        if s1==nums:#如果相同,说明没有下一个排列了,要进行升序排列

            nums[:]=sorted(nums)#题目中要原地修改,要用切片

            return #不要返回anything 在上面那行修改了即可,但是别忘了return来结束 否则错

        #特殊情况处理完,开始真正的算法部分

        lenth = len(nums)

        lelf = lenth-2#left和right是从右往左查找的“窗口”

        right = lelf+1

        ll=0#ll和rr分别记录要交换的左右两个位置

        rr=0#ll就是“上坡”的左边界,

        #rr就是在“上坡”左边界的右边,找到的比左边界大的最小数

        while(lelf>=0):#从右往左,找到第一个“上坡”,记录下左边的值

            if nums[lelf]<nums[right]:#发现上坡!

                ll = lelf

                break#记录完毕,拜拜

            lelf-=1

            right-=1

        for i in range(lenth-1,ll,-1):#从右向左寻找,记录下比他大的最小值

            if nums[i]>nums[ll]:#发现第一个比上坡左边界大的值!

                rr=i

                break#记录完毕 拜拜

        #二者交换

        nums[ll],nums[rr]=nums[rr],nums[ll]

        nums[:] = nums[:ll+1]+sorted(nums[ll+1:])#ll加1开始,往后的部分要排序

        print(nums)

小结:

  这里题目要求是要原地操作,用python的话,原地操作数组要用切片的形式。如果直接修改nums而不是nums[:],最终结果是不对的,所以要记住这个小技巧。

  这个题的过程我说的太过详细了,看起来好像挺复杂——但实际上,就是“两次查找”+找到之后进行一次交换+对后半段排个序。大概就这么简单几步~

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

JunanP

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值