LeetCode 31. 下一個排列 | Python
31. 下一個排列
題目
實現獲取下一個排列的函式,演算法需要將給定數字序列重新排列成字典序中下一個更大的排列。
如果不存在下一個更大的排列,則將數字重新排列成最小的排列(即升序排列)。
必須原地修改,只允許使用額外常數空間。
以下是一些例子,輸入位於左側列,其相應輸出位於右側列。
1,2,3 → 1,3,2
3,2,1 → 1,2,3
1,1,5 → 1,5,1
解題思路
思路:迭代
首先先理解題意,題目中要求【將給定數字序列重新排列成字典序中下一個更大的排列。如果不存在,則將數字重新排列稱最小的排列(即升序排列)】
在這裡,可能直接從文字上面來看,不太不能夠理解是什麼意思,那麼結合例子來看,先看
1,2,3 → 1,3,2
1,1,5 → 1,5,1
在這裡,你可以理解為,要將數字 123 變為下一個更大的數字,132。115 也同理。
而下面這個例子就是表示不存在更大的排列:
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. 下一個排列》問題的分析及具體實現演算法的主要內容。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/855/viewspace-2825477/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 31. 下一個排列
- 下一個排列(LeetCode)LeetCode
- LeetCode31.下一個排列LeetCode
- [LeetCode] Next Permutation 下一個排列LeetCode
- Leetcode——46. 全排列LeetCode
- 【LeetCode】46. 全排列LeetCode
- leetcode:全排列(java回溯)LeetCodeJava
- LeetCode系列46—全排列LeetCode
- LeetCode-046-全排列LeetCode
- [Leetcode]下一個更大元素IILeetCode
- LeetCode-441-排列硬幣LeetCode
- LeetCode-047-全排列 IILeetCode
- LeetCode 567. 字串的排列LeetCode字串
- LeetCode-496-下一個更大元素 ILeetCode
- Leetcode 496. 下一個更大元素 ILeetCode
- 全排列及相關擴充套件演算法(二)——求字典序下一組排列及全排列演算法套件演算法
- LeetCode46 回溯演算法求全排列,這次是真全排列LeetCode演算法
- 【leetcode】60. Permutation Sequence 全排列的第k位序的排列形式LeetCode
- LeetCode 45跳躍遊戲&46全排列LeetCode遊戲
- 字母排列(python實現)Python
- LeetCode每日一題: 排列硬幣(No.441)LeetCode每日一題
- LeetCode 1470. 重新排列陣列LeetCode陣列
- python:用pyinstaller做個排列組合的小工具Python
- 31. 資料庫基礎資料庫
- 現在有"abcdefghijkl”12個字元,將其所有的排列中按字典序排列,給出任意一種排列,說出這個排列在所有的排列中是第幾小的?字元
- Bootstrap系列 -- 31.巢狀分組boot巢狀
- LeetCode刷題進階之重新排列字串(1528)LeetCode字串
- LeetCode-116-填充每個節點的下一個右側節點指標LeetCode指標
- LeetCode-117-填充每個節點的下一個右側節點指標 IILeetCode指標
- LeetCode117-填充每個節點的下一個右側節點指標 IILeetCode指標
- Python語言的全排列怎麼提速?Python
- 實現將10個整數升序排列
- 課時31.無序列表練習(理解)
- CSS下一個兄弟元素CSS
- 逆序排列
- css兩個div在同一行排列CSS
- leetcode 面試題08.08. 有重複字串的排列組合LeetCode面試題字串
- 用js寫三個數,讓三個數從小到大排列JS