[LeetCode]31.下一个排列
题目
实现获取 下一个排列 的函数,算法需要将给定数字序列重新排列成字典序中下一个更大的排列。
如果不存在下一个更大的排列,则将数字重新排列成最小的排列(即升序排列)。
必须 原地 修改,只允许使用额外常数空间。
示例 1
输入:nums = [1,2,3]
输出:[1,3,2]
示例 2
输入:nums = [3,2,1]
输出:[1,2,3]
解析
最好自己在纸画一下4个数的字典排序,就会发现下一队列
如下规律
- 第一个队列升序排序
- 从右往前交换,当后面数列整个倒序时,需要往前升一位
- 往前升一位后,后面的队列是升序排列
- 需要升序情况(假设 i 需要升一位,k 是所需的数字)
- 这个时候
[i + 1, n]
倒序排列 - 因为这个时候
[i + 1, n]
倒序,替换i , k位置,并把队列反转就是需要的下一队列
- 这个时候
- 难点
- 不能使用额外空间
- 算法流程
- 特判
- 数组长度小于2 : 直接返回
- 数组长度 == 2 或者 倒数第二位 小于 倒数第一 : 交换最后两位数即可
- 找到需要升位的位置
pointer
- 左右指针遍历
- 右边第一个大于
nums[i]
或左边最后一个大于nums[i]
即需要升位的数字 - 替换左右指针位置(反转队列)
- 右边第一个大于
源码
from typing import List, Literal
class Solution:
def nextPermutation(self, nums: List[int]) -> None:
"""
Do not return anything, modify nums in-place instead.
"""
if not nums or len(nums) <= 1:
return
length = len(nums)
if length == 2 or nums[length - 2] < nums[length - 1]:
nums[length - 2], nums[length - 1] = nums[length - 1], nums[length - 2]
return
pointer = length - 3
while pointer >= 0:
if nums[pointer] < nums[pointer + 1]:
break
pointer = pointer - 1
left = pointer + 1
right = length - 1
current_val = nums[pointer] if pointer >= 0 else 101
is_swap = False
while left <= right:
if not is_swap and nums[right] > current_val:
nums[pointer], nums[right] = nums[right], nums[pointer]
is_swap = True
if not is_swap and nums[left] > current_val and nums[left + 1] <= current_val:
nums[left], nums[pointer] = nums[pointer], nums[left]
is_swap = True
nums[left], nums[right] = nums[right], nums[left]
left += 1
right -= 1
pass