【leetcode】31.下一个排列(python实现)

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

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

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

以下是一些例子,输入位于左侧列,其相应输出位于右侧列。

1,2,31,3,2
3,2,11,2,3
1,1,51,5,1

逻辑:

  • 1837 1873 # 最简单的一种,直接互换
  • 1873 3178 # 后面3位 873 是倒序的,没法再生成下一个元素,所以要把1来拿来,首先1 和 873 中最小的3 互换 变成 3 871 然后后面的871 按照增序排列变成178 综合就变成了3178
  • 1783 1837
  • 1583 1835
  • 1983 3189

这道题想了挺久的,附上代码,注释在代码中:

class Solution(object):
    def nextPermutation(self, nums):
        """
        :type nums: List[int]
        :rtype: None Do not return anything, modify nums in-place instead.
        """
        
        length = len(nums)
        pre = length - 2
        after = length -1
        
        while pre >= 0:
            
            if nums[pre] < nums[after]:
                temp = after
                # 当temp小于数组当中最大的数时
                while temp <= len(nums) - 1:
                    
                    #如果找到了一个temp对应的数组值小于nums[pre],则将两个数互换再进行
                    if nums[temp] <= nums[pre]:
                        nums[pre],nums[temp-1] = nums[temp-1],nums[pre]
                        break
                    # 如果遍历到最后还没找到比nums[pre]小的数,那么就让最后一个数跟num[pre]互换位置再进行排序
                    # 如123549876 ==123569874,再排序
                    if temp == len(nums)-1 and nums[temp] > nums[pre]:
                        nums[pre], nums[temp] = nums[temp], nums[pre]
                    
                    temp += 1
                #排序
                nums[pre+1:] = nums[:pre:-1]
                break
                        

            else:
                #往前移
                pre -= 1
                after -= 1
                
                if pre == -1:
                    #如果是54321类型,转换成12345
                    nums[:] = nums[::-1]
                
            
            

在评论区找到了代码逻辑更加清晰简洁的代码:

代码思路:

用nums = [1,3,5,7,6,4,2,1]来做示范吧. 首先,第一个指针从队尾开始向前遍历(i = len(nums) - 2),判断一下i+1与i的大小关系.在遍历到5之前,一直是nums[i]>nums[i+1]. 在第一个指针指向5时,第二个指针同样从队尾出发,因为在逆向遍历到i之前,一直是升序的,刚开始nums[j] <= nums[i]是一直满足的,当j停止移动时,j指向的数字是刚刚好大于nums[i]的,在例子中,j刚好指向6.

将nums[i]与nums[j]进行互换.此时nums = [1,3,6,7,5,4,2,1].此时6之后的数字是降序的,所以将6之后数字进行反转,才能达到题目要求"刚好大于原序列的效果",然后将nums[i+1:]进行反转即可.

class Solution:
    def nextPermutation(self, nums):
        """
        :type nums: List[int]
        :rtype: void Do not return anything, modify nums in-place instead.
        """
        i = len(nums) - 2
        while i >= 0 and nums[i+1]<=nums[i]:
            i -= 1
        if i >= 0:
            j = len(nums) - 1
            while j >= i  and nums[j] <=nums[i]:
                j -= 1
            self.swap(nums,i,j)
        self.reverse(nums,i+1)
                    
    def reverse(self, nums,start):
        i = start
        j = len(nums) - 1
        while i < j :
            self.swap(nums,i,j)
            i += 1
            j -= 1         
            
    def swap(self,nums,i,j):
        temp = nums[i]
        nums[i] = nums[j]
        nums[j] = temp

猜你喜欢

转载自blog.csdn.net/qq_43538596/article/details/89072471