题目
给定一个数组,其中元素的排列对应着一个字典序值,找仅大于该字典序值的字典序所对应的那种排列。注,如果给定数组拥有字典序最大,那么返回字典序最小的排列。
比如:数组[1,2,3] 的下一个排列为[2,1,3];
数组[1,1,5] 的下一个排列为[1,5,1];
思路
- 从数组的右边开始遍历,找第一个满足"nums[i-1]<nums[i]"的下标
i
; - 此时,从
nums[i,...,n-1]
中找刚好大于nums[i-1]的元素nums[j]
(注:a“刚好”大于b的意思是,在所有大于b的元素中a是最小的)
具体地,因为上述确定下标i
和j
的方法,保证了交换nums[i-1]
和nums[j]
之后,nums[i…n-1]是降序的。所以,想找“刚好大于nums[i-1]的元素nums[j]
”,可以从nums[i…n-1]的右边开始遍历着找。
交换完,要把nums[i…n-1]调成升序。(因为nums[i…n-1]原本是降序,所以可以使用双指针的方法来实现这一目的。)
比如,数组[5,1,3,2,4],确定下标i=2,j=3
,交换nums[i-1]
和nums[j]
之后,数组变成[5,2,3,1,4],这显然不是我们要的,因为还有这里加粗部分还可以进一步修正,于是对nums[i…n-1]做升序调整,得到[5,2,1,3,4]
,这就是答案——其字典序仅大于原数组[5,1,3,2,4]
的字典序。 - 遍历一遍结束时,如果上述的交换、调整操作完全没执行过,那么说明当前数组拥有最大字典序,所以 按照题意,返回排序后的数组(其字典序最小)。
代码
class Solution:
def nextPermutation(self, nums: List[int]) -> None:
n=len(nums)
flag=True
for i in range(n-1,0,-1):
if nums[i-1]<nums[i]:
idx=i
for j in range(n-1,i-1,-1):
if nums[j]>nums[i-1]:
swap(nums,j,i-1)
idx=j
break
left,right=i,n-1
while left<right:
swap(nums,left,right)
left+=1
right-=1
flag=False
break
if flag:
nums.sort()
def swap(nums,left,right):
t=nums[left]
nums[left]=nums[right]
nums[right]=t