LeetCode 31:下一个排列(Next Permutation)—— 完整题解笔记 ✅

LeetCode 31:下一个排列(Next Permutation)------ 完整题解笔记 ✅

🔗 题目链接

👉 https://leetcode.cn/problems/next-permutation/


📖 内容概要

给定一个整数数组 nums,表示一个排列,要求 原地修改 ,将其变为 字典序中下一个更大的排列

若不存在下一个更大排列,则返回最小的排列(升序)。

✅ 时间复杂度 O(n)

✅ 空间复杂度 O(1)

✅ 面试高频题


💡 解题思路(核心)

一、关键思想

  • 从右往左看:
    • 如果右侧一直递增(左 < 右),说明这部分已经是最大状态
    • 只有当某个位置"变小"时,才可能变得更大

二、三步法

✅ 第一步:从右往左找第一个"降序数"
java 复制代码
while (i >= 0 && nums[i] >= nums[i + 1]) i--;

找到的 nums[i] 是:

从右往左第一个小于它右边邻居的数

含义:

  • nums[i]可以变大的最低位
  • i 右侧是 最大后缀

✅ 第二步:找 nums[i] 右边最小的比它大的数
java 复制代码
while (j > i && nums[j] <= nums[i]) j--;
swap(nums, i, j);
  • i 右侧
  • 刚好比 nums[i] 大的最小数
  • 交换

👉 保证:

  • 排列变大
  • 增幅最小

✅ 第三步:反转 i 右侧部分
java 复制代码
reverse(nums, i + 1, n - 1);
  • 交换后右侧仍是降序
  • 反转后得到 最小后缀
  • 构成 下一个排列

三、特殊情况

情况 说明
i < 0 已是最大排列
处理方式 反转整个数组

📌 举例说明(非常重要)

示例数组

text 复制代码
nums = [1, 3, 5, 4, 2]

Step 1️⃣:找第一个降序数

从右往左:

复制代码
2 < 4 < 5 > 3

找到:

复制代码
i = 1
nums[i] = 3

✅ 3 是第一个"右边还有更大数"的数


Step 2️⃣:找右边最小的大数并交换

i = 1,右边是:

复制代码
[5, 4, 2]

从右往左找第一个大于 3 的数:

复制代码
4

交换 34

复制代码
[1, 4, 5, 3, 2]

Step 3️⃣:反转 i 右侧部分

反转 [5, 3, 2]

复制代码
[2, 3, 5]

最终结果:

复制代码
[1, 4, 2, 3, 5]

✅ 这就是 下一个排列


✅ 对比验证

排列 字典序
原排列 1 3 5 4 2
下一个 1 4 2 3 5

✅ AC 代码(Java)

java 复制代码
class Solution {
    public void nextPermutation(int[] nums) {
        int n = nums.length;
        int i = n - 2;

        // 第一步:从右往左找第一个降序的位置
        while (i >= 0 && nums[i] >= nums[i + 1]) {
            i--;
        }

        // 第二步:交换
        if (i >= 0) {
            int j = n - 1;
            while (i < j && nums[j] <= nums[i]) {
                j--;
            }
            swap(nums, i, j);
        }

        // 第三步:反转
        reverse(nums, i + 1, n - 1);
    }

    private void swap(int[] nums, int i, int j) {
        int tmp = nums[i];
        nums[i] = nums[j];
        nums[j] = tmp;
    }

    private void reverse(int[] nums, int i, int j) {
        while (i < j) {
            swap(nums, i++, j--);
        }
    }
}

⏱️ 复杂度分析

指标 复杂度
时间复杂度 O(n)
空间复杂度 O(1)

✅ 一句话总结

从右往左找到第一个"还能变大"的位置,把它换成右边最小的大数,再把后面变成最小后缀。

掌握这道题,就掌握了:

  • 字典序排列
  • 原地数组操作
  • 指针边界控制
相关推荐
:-)9 小时前
算法-归并排序
java·开发语言·数据结构·算法·排序算法
Jerry13 小时前
LeetCode 101. 对称二叉树
算法
hengcaib14 小时前
防封号电销外包公司怎么选合规线路与风控核查方法
笔记
可编程芯片开发14 小时前
基于MPPT最大功率跟踪的离网光伏发电系统Simulink建模与仿真
算法
AI科技星14 小时前
线性算子不是空间映射函数,是全域双螺旋场之间拉伸、旋转、耦合、坍缩的跨空间标准化变换载体《全域数学vs传统数学:人类文明进阶200讲》第80讲
线性代数·算法·矩阵·数据挖掘·回归·乖乖数学·全域数学
米罗篮14 小时前
矩阵快速幂 (Exponentiation By Squaring Applied To Matrices)
c++·线性代数·算法·矩阵
dream_home840714 小时前
图像算法模型NPU适配与算法服务实战指南
人工智能·python·算法·npu 图像服务
大鱼>15 小时前
多宠物家庭智能管理平台:云端架构与多设备协同实战
python·算法·iot·宠物
To_OC15 小时前
LC 22 括号生成:刷完这道题,我终于搞懂回溯剪枝了
javascript·算法·leetcode
To_OC16 小时前
LC 39 组合总和:回溯入门必刷题,我踩过的两个坑都在这了
javascript·算法·leetcode