LeetCode 31. 下一個排列 | Python

31. 下一個排列


題目


實現獲取下一個排列的函數,算法須要將給定數字序列從新排列成字典序中下一個更大的排列。python

若是不存在下一個更大的排列,則將數字從新排列成最小的排列(即升序排列)。算法

必須原地修改,只容許使用額外常數空間。數組

如下是一些例子,輸入位於左側列,其相應輸出位於右側列。bash

1,2,3 → 1,3,2
3,2,1 → 1,2,3
1,1,5 → 1,5,1

解題思路


思路:迭代微信

首先先理解題意,題目中要求【將給定數字序列從新排列成字典序中下一個更大的排列。若是不存在,則將數字從新排列稱最小的排列(即升序排列)】函數

在這裏,可能直接從文字上面來看,不太不可以理解是什麼意思,那麼結合例子來看,先看spa

1,2,3 → 1,3,2
1,1,5 → 1,5,1

在這裏,你能夠理解爲,要將數字 123 變爲下一個更大的數字,132。115 也同理。code

而下面這個例子就是表示不存在更大的排列:blog

3,2,1 → 1,2,3

321 已是最大的了,那麼就將其排列爲最小的排列(升序排列),獲得結果 123。索引

其實從上面的例子中,多多少少也可以看出來,在這裏實際上是從後面開始找,當找到相鄰升序的兩個數字,在這裏將它們進行交換,這樣就可以獲得更大的排列。

其實這裏還有一部分的內容,在題目中是比較難看出來的,題目中【下一個】這個概念,其實要找到的是變化先後的排列,增長的幅度儘量小。好比,下面的例子:

1,2,3,4,5 → 1,2,3,5,4
1,2,3,5,4 → 1,2,4,3,5

第一個示例,根據上面觀察所得,便是將 4 和 5 進行替換,獲得更大的排列,12354。

後面的示例中 12354,獲得排列的結果 12435。在這裏,交換的是 3 和 4,這裏其實交換的數字是儘量小的大數和前面的小數,因此並非 3 和 5 進行交換,而交換後的全部數還須要重置升序。所得出的結果是 12435,而不是 12453。

這就是關於題意的簡單分析,下面看如何實現算法:

  • 首先須要明確的是從後面往前查找第一個相鄰升序的兩個元素所在的位置(i,j),知足 A[i] < A[j]。並且,從位置 j 日後的元素是降序的。
  • 在 j 日後的元素中,一樣是從後往前找,找到第一個知足 A[i] < A[k] 的元素,將其二者進行交換。
  • 前面說了, 從 j 日後必定是降序的,那麼交換之後確定也是降序的(由於找到 A[k] 是第一個比 A[i] 大的數字,因爲是從後往前找,k所在位置左邊的數字勢必比當前 i 所在位置的數字大,而右邊的數字也就比其小),這個時候,要將這部分降序,逆轉爲升序,這樣才能保證排列先後儘量小的增幅。
  • 考慮特殊的狀況,也就是整個排列是降序,便是最大的的排列時,執行上面所說逆轉爲升序便可。

具體的代碼實現以下。

代碼實現


class Solution:
    def nextPermutation(self, nums: List[int]) -> None:
        """
        Do not return anything, modify nums in-place instead.
        """
        if len(nums) < 2:
            return

        n = len(nums)

        # 從數組右往前進行遍歷,查找相鄰升序元素
        i = n - 2
        j = n - 1
        while i > 0 and nums[i] >= nums[j]:
            i -= 1
            j -= 1
        # 這裏有一種狀況,就是循環結束後,i 爲 0 且索引 0 位置的數是最大的狀況
        # 那這裏就表示排列就是最大的排列,將其逆轉升序
        if i == 0 and nums[i]==max(nums):
            nums.reverse()
        else:
            # 當找到相鄰的升序元素時
            # 再次從後往前找到一個比 nums[i] 大但相比其餘元素儘量小的數
            k = n - 1
            while nums[i] >= nums[k]:
                k -= 1
            # 交換兩個元素
            nums[i], nums[k] = nums[k], nums[i]

            # 如今 j 到後面的元素是降序的,這裏要將其升序
            length = n - j + 1
            for x in range(length // 2):
                nums[j+x], nums[n-1-x] = nums[n-1-x], nums[j+x]

實現結果


實現結果


以上就是關於《31. 下一個排列》問題的分析及具體實現算法的主要內容。

歡迎關注微信公衆號《書所集錄》
相關文章
相關標籤/搜索