返回
LeetCode 31:下一个排列(双指针法)
前端
2023-09-13 02:17:58
LeetCode 31:下一个排列
题目
给定一个排列整数数组 nums
,编写一个函数对其进行重新排列,使其变为下一个字典序更大的排列。如果不存在下一个更大的排列,则将数组重新排列为第一个排列。
示例 1:
输入:nums = [1,2,3]
输出:[1,3,2]
思路 1:双指针法
- 查找降序子序列的末尾: 从后往前遍历
nums
,找到第一个降序子序列的末尾元素nums[i]
。如果不存在降序子序列,则说明当前排列已经是最大的排列,返回第一个排列。 - 查找大于
nums[i]
的最小元素: 从i
开始,从后往前遍历nums
,找到第一个大于nums[i]
的元素nums[j]
。 - 交换
nums[i]
和nums[j]
: 交换nums[i]
和nums[j]
,使降序子序列末尾的元素变大。 - 反转
nums[i+1:]
:nums[i+1:]
是一个降序子序列,将其反转可以得到下一个最大的子序列。 - 返回重新排列的
nums
: 返回重新排列后的nums
数组。
代码:
/**
* @param {number[]} nums
* @return {void} Do not return anything, modify nums in-place instead.
*/
const nextPermutation = (nums) => {
if (nums.length < 2) return;
// 1. 查找降序子序列的末尾
let i = nums.length - 2;
while (i >= 0 && nums[i] >= nums[i + 1]) i--;
// 如果不存在降序子序列,返回第一个排列
if (i < 0) {
nums.sort((a, b) => a - b);
return;
}
// 2. 查找大于 nums[i] 的最小元素
let j = nums.length - 1;
while (nums[j] <= nums[i]) j--;
// 3. 交换 nums[i] 和 nums[j]
const temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
// 4. 反转 nums[i+1:]
const reversed = nums.slice(i + 1).reverse();
nums.splice(i + 1, nums.length - i - 1, ...reversed);
};