Problem Definition:數組
Implement next permutation, which rearranges numbers into the lexicographically next greater permutation of numbers.spa
If such arrangement is not possible, it must rearrange it as the lowest possible order (ie, sorted in ascending order).code
The replacement must be in-place, do not allocate extra memory.blog
Here are some examples. Inputs are in the left-hand column and its corresponding outputs are in the right-hand column.it
1,2,3
→ 1,3,2
3,2,1
→ 1,2,3
1,1,5
→ 1,5,1
io
Solution:class
明確一個問題:什麼樣的組合是最大的?什麼樣又是最小的?答:非升序的組合最大,非降序的組合最小。call
慄如:3 2 1 是這仨數能組成的組大permutation,慄如:1 2 2 5 是這四個數能組成的最小permutation。next
因而問題變得很straightforward。求下一個permutation,要作的就是如下的事情:sort
1)從尾部開始往回,找到第一個發現降序的位置。好比6 7 5 4 3 2 1,找到的位置是6所在的位置,記爲 i=0。
在這個位置以後的 7 5....是降序的,說明已經達到了這些數能組成的最大可能。所以 i 這個位置是第一個若是改變它就能增大整個串的位置。
固然,比 i 小的某些位置,改變它們也可能增大串,可是由於 i 是最靠後的,所以增大的最小,咱們的目標就是最小限度(就是增長到下一個)地增大串。
若是直到數組首,都沒找到這樣的位置,說明已是最大permutation,記 i=-1,而且跳過步驟 2). O(n)
2)而後要找一個元素來替換 i 所指的元素。應該從 i 以後的元素裏找。已經知道 i 以後的元素是從尾部開始向前呈現升序(或者非降序)的,所以應該從尾部開始往前,
找到第一個大於 i 所值元素的元素,其位置記爲 j。如今交換 i 和 j 指的元素。O(n)
3)如今的 i 位置的元素,以及比 i 更小的位置的元素,都到了它們應該到的位置。而 i 以後的元素,呈現的是降序(i+1到j-1的元素都大於j的元素,j+1到最尾的元素都小於j的元素)。
爲了使 i+1 開始,到最尾的元素造成它們能造成的最小部分permutation,應該把它們逆置,能夠首末兩兩交換。(若是步驟1)中獲得的 i 是 -1,則恰好對應應該把整個串反轉的狀況)。仍是O(n)
寫成代碼就是醬紫的:
1 # @param {integer[]} nums 2 # @return {void} Do not return anything, modify nums in-place instead. 3 def nextPermutation(self, nums): 4 n=len(nums) 5 if n<2: 6 return 7 i,j,pLeft,pRight=n-2,n-1,-1,n-1 8 while i>=0 and nums[i]>=nums[i+1]: 9 i-=1 10 if i>=0: 11 while j>i and nums[j]<=nums[i]: 12 j-=1 13 #must be j>i 14 nums[i],nums[j]=nums[j],nums[i] 15 pLeft=i+1 16 while pLeft<pRight: 17 nums[pLeft],nums[pRight]=nums[pRight],nums[pLeft] 18 pLeft+=1 19 pRight-=1