LeetCode31.下一個排列

菜鳥xk_110發表於2020-11-14

LeetCode31. 下一個排列

1.題目描述:

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

如果不存在下一個更大的排列,則將數字重新排列成最小的排列(即升序排列)。

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

示例 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]

2.解題思路:

首先我們需要了解什麼是字典序:
對於數字1、2、3…n的排列,不同排列的先後關係是從左到右逐個比較對應的數字的先後來決定的。例如對於5個數字的排列 12354和12345,排列12345在前,排列12354在後。按照這樣的規定,5個數字的所有的排列中最前面的是12345,最後面的是 54321。

之後我們希望下一個數比當前數大,這樣才滿足“下一個排列”的定義。因此只需要將後面的 大數 與前面的 小數 交換,就能得到一個更大的數。比如 123456,將 5 和 6 交換就能得到一個更大的數 123465。
我們還希望下一個數增加的幅度儘可能的小,這樣才滿足“下一個排列與當前排列緊鄰“的要求。為了滿足這個要求,我們需要:在儘可能靠右的低位進行交換,需要從後向前查詢將一個 儘可能小的 大數 與前面的 小數 交換。比如 123465,下一個排列應該把 5 和 4 交換而不是把 6 和 4 交換
將 大數 換到前面後,需要將 大數 後面的所有數重置為升序,升序排列就是最小的排列。以 123465 為例:首先按照上一步,交換 5 和 4,得到 123564;然後需要將 5 之後的數重置為升序,得到 123546。顯然 123546 比 123564 更小,123546 就是 123465 的下一個排列

3.Python實現

class Solution:
    def nextPermutation(self, nums: List[int]) -> None:
        i = len(nums) - 2
        while i >= 0 and nums[i] >= nums[i + 1]:
            i -= 1
        if i >= 0:
            j = len(nums) - 1
            while j >= 0 and nums[i] >= nums[j]:
                j -= 1
            nums[i], nums[j] = nums[j], nums[i]
        
        left, right = i + 1, len(nums) - 1
        while left < right:
            nums[left], nums[right] = nums[right], nums[left]
            left += 1
            right -= 0

4.總結:

剛開始連題都讀不懂,知道啥是字典序之後又想了好久,在位置的交換上一直搞的迷迷瞪瞪的,後來才想清楚。

相關文章