实现获取下一个排列的函数,算法需要将给定数字序列重新排列成字典序中下一个更大的排列。
如果不存在下一个更大的排列,则将数字重新排列成最小的排列(即升序排列)。必须原地修改,只允许使用额外常数空间。
以下是一些例子,输入位于左侧列,其相应输出位于右侧列。
1,2,3 → 1,3,2
3,2,1 → 1,2,3
1,1,5 → 1,5,1
根据题意可知,题目给定了一个数字序列,我们需要将给定的数字序列进行一个重排序,即数字之间进行位置互换。如果互换后可以得到更大的序列,则返回当前序列在字典序中的下一个排列;如果不存在更大的排列,则返回最小的排列。
字典序: 对于数字1、2、3…n的排列,不同排列的先后关系是从左到右逐个比较对应的数字的先后来决定的。例如对于5个数字的排列 12354和12345,排列12345在前,排列12354在后。按照这样的规定,5个数字的所有的排列中最前面的是12345,最后面的是 54321。
字典序排序算法:
- 从序列中从右至左找第一个左邻小于右邻的数(从后向前查看逆序区域,找到逆序区域的前一位,也就是数字置换的边界)
- 把逆序区域的前一位和逆序区域中刚刚大于它的数字交换位置
- 把原来的逆序区域转为顺序
根据字典序的定义和字典序排序算法的描述,寻找给定序列的下一个字典序中更大的序列的做法如下所示:例如现在序列为 [ 1 , 2 , 3 , 5 , 4 ] [1,2,3,5,4] [1,2,3,5,4],从后往前找逆序区 [ 5 , 4 ] [5,4] [5,4],然后将逆序区进行顺排将其重新赋值给序列的对应区间;然后在逆序区间中寻找第一个比逆序区前一个数字 3 3 3大的数字 4 4 4,然后将其和 3 3 3进行互换即可。
因此,我们首先需要判断是否还存在更大的排列,这可以通过观察给定数组中元素的排序得到。
-
如果当前元素已经是降序排列,则必然不可能得到比它更大的排列,则直接求其最小的排列,也就是数组反转后对应的值
-
如果不是降序排列,则按照上面的做法进行下一个序列的寻找
AC code
class Solution:
def nextPermutation(self, nums: List[int]) -> None:
"""
Do not return anything, modify nums in-place instead.
"""
if nums == []:
return []
if sorted(nums, reverse = True) == nums:
return nums.reverse()
for i in range(len(nums)-1, 0, -1):
if nums[i] > nums[i-1]:
# 逆序区
others = nums[i:]
# 将逆序区进行顺排并将其重新赋值给逆序区
others = sorted(others)
nums[i:] = others
# 寻找第一个比nums[i]大的数字和nums[i]进行互换
for n in others:
if n > nums[i - 1]:
index = others.index(n) + i
t = nums[i - 1]
nums[i - 1] = nums[index]
nums[index] = t
break
return