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