二刷 LeetCode:75. 颜色分类 & 31. 下一个排列 复盘笔记

目录

[一、75. 颜色分类(荷兰国旗问题)](#一、75. 颜色分类(荷兰国旗问题))

题目回顾

思路复盘

核心思想

[Python 代码实现](#Python 代码实现)

[易错点 & 二刷心得](#易错点 & 二刷心得)

[二、31. 下一个排列](#二、31. 下一个排列)

题目回顾

思路复盘

核心步骤

[Python 代码实现](#Python 代码实现)

[易错点 & 二刷心得](#易错点 & 二刷心得)

[三、两道题的共性总结 & 二刷收获](#三、两道题的共性总结 & 二刷收获)


这两道题是数组 / 排序专题的经典中等题,也是面试中常考的 "原地操作" 类型,非常适合用来巩固双指针和贪心思想。二刷时我们重点拆解核心思路、优化写法,并总结通用解题模板。


一、75. 颜色分类(荷兰国旗问题)

题目回顾

给定一个包含红色、白色和蓝色、共 n 个元素的数组 nums,原地对它们进行排序,使得相同颜色的元素相邻,并按照红色、白色、蓝色顺序排列。我们使用整数 012 分别表示红色、白色和蓝色。

思路复盘

这道题的最优解是三指针法(荷兰国旗问题),时间复杂度 \(O(n)\),空间复杂度 \(O(1)\),一次遍历完成排序。

核心思想

定义三个指针:

  • p0:指向 0 的右边界,初始为 0
  • p2:指向 2 的左边界,初始为 len(nums)-1
  • curr:当前遍历的元素指针,初始为 0

遍历规则:

  1. nums[curr] == 0:和 nums[p0] 交换,p0++curr++
  2. nums[curr] == 2:和 nums[p2] 交换,p2--(注意 curr 不增加,因为交换来的元素需要再判断)
  3. nums[curr] == 1:直接 curr++
Python 代码实现

python

运行

复制代码
def sortColors(nums: list[int]) -> None:
    p0 = curr = 0
    p2 = len(nums) - 1
    while curr <= p2:
        if nums[curr] == 0:
            nums[p0], nums[curr] = nums[curr], nums[p0]
            p0 += 1
            curr += 1
        elif nums[curr] == 2:
            nums[curr], nums[p2] = nums[p2], nums[curr]
            p2 -= 1
        else:
            curr += 1

易错点 & 二刷心得

  1. 边界控制 :循环条件必须是 curr <= p2,因为 p2 左边的元素还未处理完。
  2. 交换 2 时的指针处理 :交换 currp2 后,curr 不能自增,因为新交换来的元素可能是 0 或 2,需要再次判断。
  3. 原地修改:题目要求不使用额外空间,所以不能用计数排序后再重写数组,三指针法是最优解。

二、31. 下一个排列

题目回顾

实现获取下一个排列的函数,算法需要将给定数字序列重新排列成字典序中下一个更大的排列。如果不存在下一个更大的排列,则将数字重新排列成最小的排列(即升序排列)。必须原地修改,只允许使用额外常数空间。

思路复盘

这道题的核心是贪心思想,找到 "下一个更大" 的排列,关键步骤可以总结为 "找、换、反转" 三步。

核心步骤
  1. :从后往前找第一个 nums[i] < nums[i+1] 的位置 i,这个位置是 "下降点",后面的元素是降序的。
  2. :从后往前找第一个比 nums[i] 大的元素 nums[j],交换 nums[i]nums[j]
  3. 反转 :将 i 之后的元素反转,使其变为升序,这样得到的就是比原排列大的最小排列。
Python 代码实现

python

运行

复制代码
def nextPermutation(nums: list[int]) -> None:
    n = len(nums)
    # 步骤1:找下降点
    i = n - 2
    while i >= 0 and nums[i] >= nums[i+1]:
        i -= 1
    # 步骤2:如果不是最后一个排列,找比nums[i]大的最小数并交换
    if i >= 0:
        j = n - 1
        while nums[j] <= nums[i]:
            j -= 1
        nums[i], nums[j] = nums[j], nums[i]
    # 步骤3:反转i之后的部分
    left, right = i + 1, n - 1
    while left < right:
        nums[left], nums[right] = nums[right], nums[left]
        left += 1
        right -= 1

易错点 & 二刷心得

  1. 下降点的理解:如果整个数组是降序的,说明没有下一个排列,直接反转整个数组即可。
  2. 交换后反转的必要性 :交换 nums[i]nums[j] 后,i 之后的部分仍然是降序的,反转后才能变成升序,得到最小的更大排列。
  3. 边界处理 :当 i < 0 时,说明数组是降序的,直接反转整个数组即可,无需额外处理。

三、两道题的共性总结 & 二刷收获

  1. 原地操作的核心思想 :两道题都要求在不使用额外空间的情况下修改数组,核心都是通过双指针 / 多指针实现元素的交换和重排。
  2. 贪心算法的应用
    • 颜色分类:通过指针划分区域,一次遍历完成分类,局部最优(每次把元素放到正确位置)得到全局最优。
    • 下一个排列:通过 "找下降点、交换、反转" 三步,找到字典序下的最小更大排列,同样是贪心思想的体现。
  3. 面试高频考点
    • 颜色分类:重点考察三指针法和荷兰国旗问题,是多指针思想的经典应用。
    • 下一个排列:重点考察对排列字典序的理解和原地修改的技巧,面试中常被追问时间复杂度和空间复杂度优化。
相关推荐
风筝在晴天搁浅1 小时前
LeetCode 378.有序矩阵中第K小的元素
算法·矩阵
liurendonews2 小时前
刘韧微积分笔记之六:投降,还是战斗,这是一个问题?
笔记
小雅痞2 小时前
[Java][Leetcode middle] 3. 无重复字符的最长子串
java·开发语言·leetcode
qeen872 小时前
【算法笔记】简单贪心
c++·笔记·算法·贪心算法
ErizJ2 小时前
Kubernetes|学习笔记
笔记·学习·kubernetes
羊群智妍2 小时前
2026 AI搜索优化|免费GEO监测工具亲测推荐
笔记
ting94520002 小时前
动手学深度学习(PyTorch版)深度详解(10): 优化算法 全解
人工智能·pytorch·深度学习·算法
ouliten2 小时前
[Triton笔记1]核心概念
笔记·python·深度学习·triton
ulias2122 小时前
leetcode热题 - 5
数据结构·算法·leetcode