leetcode中的原题是:
实现获取下一个排列函数,这个算法需要将数字重新排列成字典序中数字更大的排列。
如果不存在更大的排列,则重新将数字排列成最小的排列(即升序排列)。
修改必须是原地的,不开辟额外的内存空间。
这是一些例子,输入位于左侧列,其相应输出位于右侧列。1,2,3
→ 1,3,2
3,2,1
→ 1,2,3
1,1,5
→ 1,5,1
这个问题其实解释的很清楚了,但是不知道当时怎么了,我以为非常复杂。
假如传入的是数组,为nums。
我想象中的的解法是,从给定数组的后面往前面找,找到给定数组中的一个索引,要求是这个索引(index)对应的值大于索引(index+1)对应的值,然后让这两个索引对应的值互相交换就OK了。(假如index之后的元素为abcde,那么abcde是从大到小>排列的,即a>b>c>d>e)
为什么这么找呢?
是因为,交换上述索引的值可以使的整体增大的值最小。
你看啊,假如nums=[1,4,5,2,3],交换2和3的位置边得的排列(变成14532),是小于4和5交换得到的排列的(变成15423)。这个很简单吧?(一个是千位数的增加,一个是十位数的增加)
但是这样得到就是想要的结果吗?
假如nums=[1,3,6,5,4,2],交换3和6的值就是下一个排列吗?
不是的,由13开头变为16开头,要知道中间还有15或者14开头的,那么到了这一步你是否想到交换哪两个值的位置了?
当然是3和4的位置。
这就解决了到底应该和谁交换的问题。和谁交换呢?找到了索引index和index+1之后就应该交换索引大于index的最小的大于index索引对应的值,就是3后面最小的大于3的值4,那么就应该交换3和4的位置。
那么交换完了位置就可以了吗?
这个是不行的,因为交换完了之后,就变成146532,在此之前还有142356是不是?
交换完之后index之后的值,是从大往小排列的。那么14开头最小的排列就是咱们要找的排列。所以应该完成对index之后的值进行逆序排列。然后就解决了这个问题。
class Solution:
def nextPermutation(self, nums):
if len(nums)<2:
return
ind=len(nums)-1
while nums[ind-1]>=nums[ind] and ind>0:
ind-=1
if ind==0:
self.traverse(nums,0,len(nums)-1)
return
else:
for i in range(len(nums)-1,ind-1,-1):
if nums[i]>nums[ind-1]:
nums[i],nums[ind-1]=nums[ind-1],nums[i]
self.traverse(nums,ind,len(nums)-1)
return
def traverse(self,nums,start,end):
while start<end:
nums[start],nums[end]=nums[end],nums[start]
start+=1
end-=1