題目
實現獲取下壹個排列的函數,算法需要將給定數字序列重新排列成字典序中下壹個更大的排列。
如果不存在下壹個更大的排列,則將數字重新排列成最小的排列(即升序排列)。
必須 原地 修改,只允許使用額外常數空間。
以下是壹些例子,輸入位於左側列,其相應輸出位於右側列。
1,2,3 → 1,3,2
3,2,1 → 1,2,3
1,1,5 → 1,5,1
題意分析
看具體例子,壹個排列為124653,如何找到它的下壹個排列,因為下壹個排列壹定與124653有盡可能長的前綴,所以,腦洞大開壹下,從後面往前看這個序列,如果後面的若幹個數字有下壹個排列,問題就得到了解決。
第壹步:找最後面1個數字的下壹個全排列。
124653,顯然最後1個數字3不具有下壹個全排列。
第二步:找最後面2個數字的下壹個全排列。
124653,顯然最後2個數字53不具有下壹個全排列。
第三步:找最後面3個數字的下壹個全排列。
124653,顯然最後3個數字653不具有下壹個全排列。
------插曲:到這裏相信大家已經看出來,如果壹個序列是遞減的,那麽它不具有下壹個排列。
第四步:找最後面4個數字的下壹個全排列。
124653,我們發現顯然最後4個數字4653具有下壹個全排列。因為它不是遞減的,例如6453,5643這些排列都在4653的後面。
我們總結上面的操作,並總結出重復上面操作的兩種終止情況:
1:從後向前比較相鄰的兩個元素,直到前壹個元素小於後壹個元素,停止
2:如果已經沒有了前壹個元素,則說明這個排列是遞減的,所以這個排列是沒有下壹個排列的。
124653這個排列終止情況是上面介紹的第壹種,從後向前比較相鄰的2個元素,遇到4<6的情況停止。
並且我們可以知道:
1:124653和它的下壹個排列的公***前綴為12(因為4653存在下壹個排列,所以前面的數字12保持不變)
2:4後面的元素是遞減的(上面介紹的終止條件是前壹個元素小於後壹個元素,這裏是4<6)
現在,我們開始考慮如何找到4653的下個排列,首先明確4後面的幾個數字中至少有壹個大於4.
4肯定要和653這3個數字中大於4的數字中(6,5)的某壹個進行交換。這裏就是4要和6,5中的某壹個交換,很明顯要和5交換,如果找到這樣的元素呢,因為我們知道4後面的元素是遞減的,所以在653中從後面往前查找,找到第壹個大於4的數字,這就是需要和4進行交換的數字。這裏我們找到了5,交換之後得到的臨時序列為5643.,交換後得到的643也是壹個遞減序列。
所以得到的4653的下壹個臨時序列為5643,但是既然前面數字變大了(4653--->5643),後面的自然要變為升序才行,變換5643得到5346.
所以124653的下壹個序列為125346.
看壹個permutation,比如
125430
從末尾開始,找到decreasing subsequence,5430,因為來調5330無論怎麽調,都不可能有比它更小的,數也被自然的分成兩部分(1,2) 和 (5,4,3,0)
下壹步是找這個sequence裏面第壹個比前面部分,比2大的,3,也很容易理解,因為下壹個必定是(1,3)打頭
交換 3和2 ,變成 (1,3,5,4,2,0),再把後面的部分reverse,得到後面部分可得到的最小的
這個時候,得到下壹個sequence 130245`
思路
暴力法,從後向前搜索,直到出現滿足交換的數。