LeetCode-中等-31. 下一个排列

LeetCode-中等-31. 下一个排列

题目

引用自:LeetCode-中等-31. 下一个排列(如有侵权联系删除)

整数数组的一个 排列 就是将其所有成员以序列或线性顺序排列。

  • 例如,arr = [1,2,3] ,以下这些都可以视作 arr 的排列:[1,2,3][1,3,2][3,1,2][2,3,1]

整数数组的 下一个排列 是指其整数的下一个字典序更大的排列。更正式地,如果数组的所有排列根据其字典顺序从小到大排列在一个容器中,那么数组的 下一个排列 就是在这个有序容器中排在它后面的那个排列。如果不存在下一个更大的排列,那么这个数组必须重排为字典序最小的排列(即,其元素按升序排列)。

  • 例如,arr = [1,2,3] 的下一个排列是 [1,3,2]
  • 类似地,arr = [2,3,1] 的下一个排列是 [3,1,2]
  • arr = [3,2,1] 的下一个排列是 [1,2,3] ,因为 [3,2,1] 不存在一个字典序更大的排列。
    给你一个整数数组 nums,找出 nums 的下一个排列。

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

示例 1:

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

示例 2:

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

示例 3:

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

提示:

  • 1 <= nums.length <= 100
  • 0 <= nums[i] <= 100

解题:

没什么好说的!做他,首先分析一下,因为想找到下一个更大的排列,那我们肯定是想要找到大于当前排列的大一丢丢的那个就好了,也就是交换其中部分数值所处的位置(*注意不只是交换两个数,因为只交换两个很多时候是不满足条件的,后面我们可以看到),为了到达这个目的我们首先可以想到,应该尽可能在把低位(靠近列表右边的那些)上的某个数值与其后面的某个数值交换,再调整某些位以实现上述要求:
例如:

  • [18, 0, 23, 25, 24, 22]

我们一眼看上去,第一步,会想着拿23去和24交换位置,而不是将1824交换位置,因为23相对18而言,其处于更低的位。

整个过程而言:
首先我们会从低位看起,看24与后面的某些数值交换后,是否能找到更大排列,但24后面只有22,交换之后排列变得更小了,并不可以。
接下来看25,同样,与后面的24,或者22交换,排列会更小,也不可以。
接下来看23,我们发现他与后面的2425交换都会变得排列更大,但此时我们拿它和谁交换呢,当然是24呀,因为24是后面那些可以用来交换的两个个中,最小的那个。这样之后便得到[18, 0, 24, 25, 23, 22],但是很快我们便能发现这样交换之后,这并不是正解,因为2322交换之后,我们还需要调整23后面的那些值,才能得到正解[18, 0, 24, 22, 23, 25]
所以最后一步,当我们在把22交换走以后,只需要对该位后面的数再排序一便就好了。

整体思想:
尽量保持高位不动,从低位去做一些改变使得能尽量找到大于当前排列,却又是最小的那组排列。
循环探索,从最低位开始逐步向高位走(也就是倒序遍历列表各个位),每次判断当前位置数值,与其后面的数值能否重新组合,生成更大的排列。在判断的过程中,每次尝试找到后面那些位中,大于当前位数值的值,却又是后面那些位中尽量小的。这个过程我们可以首先对后面的那些数值进行排序,然后正序逐一判断是否大于当前值,这样找到的第一个值就满足上述条件,然后将找到的该值与当前循环位的值交换,最后将当前循环位后面的那些数值做一个排序就好了。若是循环探索的过程中,一直没找到可以交换的值,说明该组排列本身就是最大的,那么依题,将该排列,reverse一下就可以得到最小排列了。

代码:

class Solution:
    def nextPermutation(self, nums):
        """
        Do not return anything, modify nums in-place instead.
        """
        length = len(nums)
        if length < 1:
            return nums
        i = length - 2
        #从低位向高位探索
        while i > -1:
        	#找第i位后面,是否有合适的值与第i位值交换
        	#整个过程因为要保证原地操作,所以需要额外的临时存储空间
            temp1 = nums[i+1:]
            temp1.sort()
            switch_num = None
            #排序后循环判断是否有合适值
            for num in temp1:
                if num > nums[i]:
                	#若是有的话就记录下来,并break
                    switch_num = num
                    break
            #若是有合适的值,则定位该值的下标
            if switch_num != None:
                for j in range(i + 1, length):
                    if nums[j] == switch_num:
                        break
                #找到该值后,交换,并把第i位后面的值排序
                nums[i], nums[j] = nums[j], nums[i]
                temp2 = nums[i + 1:]
                temp2.sort()
                for k in range(len(temp2)):
                    nums[i + 1 + k] = temp2[k]
                return
            i -= 1
        nums.reverse()

LeetCode-中等-31. 下一个排列

测试:

class Solution:
    def nextPermutation(self, nums):
        """
        Do not return anything, modify nums in-place instead.
        """
        length = len(nums)
        if length < 1:
            return nums
        i = length - 2
        #从低位向高位探索
        while i > -1:
        	#找第i位后面,是否有合适的值与第i位值交换
        	#整个过程因为要保证原地操作,所以需要额外的临时存储空间
            temp1 = nums[i+1:]
            temp1.sort()
            switch_num = None
            #排序后循环判断是否有合适值
            for num in temp1:
                if num > nums[i]:
                	#若是有的话就记录下来,并break
                    switch_num = num
                    break
            #若是有合适的值,则定位该值的下标
            if switch_num != None:
                for j in range(i + 1, length):
                    if nums[j] == switch_num:
                        break
                #找到该值后,交换,并把第i位后面的值排序
                nums[i], nums[j] = nums[j], nums[i]
                temp2 = nums[i + 1:]
                temp2.sort()
                for k in range(len(temp2)):
                    nums[i + 1 + k] = temp2[k]
                return
            i -= 1
        nums.reverse()
if __name__=='__main__':
    print('测试1:')
    a = [4, 2, 0, 2, 3, 2, 0]
    s = Solution()
    s.nextPermutation(a)
    print('输入:nums = [4, 2, 0, 2, 3, 2, 0]')
    print('输出:',a)

    print('\n测试2:')
    a = [1, 3, 2]
    s.nextPermutation(a)
    print('输入:nums = [1, 3, 2]')
    print('输出:', a)

    print('\n测试3:')
    a = [4, 3, 2, 1]
    s.nextPermutation(a)
    print('输入:nums = [4, 3, 2, 1]')
    print('输出:', a)

LeetCode-中等-31. 下一个排列-测试

总结:

本身以为很简单,结果结果,哎,错了好几遍,耽误好一会,思维还是要缜密一点才行呀,不可马虎大意。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值