https://leetcode.com/problems/next-permutation/
参考:http://fisherlei.blogspot.hk/2012/12/leetcode-next-permutation.html
http://blog.csdn.net/m6830098/article/details/17291259
http://www.cnblogs.com/zuoyuan/p/3780167.html
算法巧妙。记住那个算法流程图
思路:
总体来说就是从后往前找到第一个递减的数,然后在这个数的右半部分中找到一个比这个数大的最小值,交换这两个值,然后对右半部分排序就可以了.这里的排序其实就是逆置就行。
先看前面2排的话,可以看出来第二排是比第一排要大的,参考字符串比较大小的问题。那么第2个排列是不是第一个排列的下一个排列呢。很明显不是,第3个排列才是, 那么如何获取到下一个排列呢。步骤比较简单:假设数组大小为 n
1.从后往前,找到第一个 A[i-1] < A[i]的。也就是第一个排列中的 6那个位置,可以看到A[i]到A[n-1]这些都是单调递减序列。
2.从 A[n-1]到A[i]中找到一个比A[i-1]大的值(也就是说在A[n-1]到A[i]的值中找到比A[i-1]大的集合中的最小的一个值)
3.交换 这两个值,并且把A[n-1]到A[i]排序,从小到大。A[n-1]到A[i]其实已经是逆序的,只需要将其变成正序即可
class Solution(object):
def nextPermutation(self, nums):
"""
:type nums: List[int]
:rtype: void Do not return anything, modify nums in-place instead.
"""
if len(nums) <= 1: return
partition = -1
for i in range(len(nums)-2, -1, -1):
if nums[i] < nums[i+1]:
partition = i
break
if partition == -1: #如果数字是从后往前一直都递增的话,那么就说明已经是排列数中的最大值了,e.g. 321
nums.reverse()
return
else:
for i in range(len(nums)-1, partition, -1):
if nums[i] > nums[partition]:
nums[i],nums[partition] = nums[partition],nums[i]
break
left = partition+1; right = len(nums)-1
while left < right:#在交换完partition之后,其实这一部分已经是有序的,现在只需要让其正序就行。
nums[left],nums[right] = nums[right],nums[left]
left+=1; right-=1
自己重写code
class Solution(object):
def nextPermutation(self, nums):
"""
:type nums: List[int]
:rtype: void Do not return anything, modify nums in-place instead.
"""
partition = -1
if len(nums) < 2: return
for i in xrange(len(nums) - 2, -1, -1):
if nums[i] < nums[i + 1]:
partition = i
break # 不要忘记break
#print partition
if partition != -1:
for i in xrange(len(nums) - 1, -1, -1):
if nums[i] > nums[partition]:
nums[i], nums[partition] = nums[partition], nums[i]
break #不要忘记break
i,j = partition + 1, len(nums) - 1
while i < j:
nums[i], nums[j] = nums[j], nums[i]
i += 1
j -= 1