当前位置: 首页 > ops >正文

刷题心得:荷兰国旗问题与三指针法题目背景

前言

最近在刷 LeetCode 时遇到了经典的 "荷兰国旗问题"(LeetCode 75 题:颜色分类)。

题目要求:

        原地对包含 0、1、2 的数组进行排序,

        使得相同颜色的元素相邻,

        并按照红 (0)、白 (1)、蓝 (2) 的顺序排列,

        且不能使用内置的 sort 函数。

前期思考

我想着遇到数组的排序问题,首先是得先遍历一次数组,用三个变量统计0  1  2的个数,再通过循环遍历进行数组的重写。

但很显然这种办法是很笨的,时间复杂度是 O (n),空间复杂度是 O (1),虽然能 AC,但显然不是最优解

因此在询问大佬,通过大佬的思路下知道了只使用常数空间的一趟扫描算法

因此得出了要使用巧妙的指针。

理解三指针法:荷兰国旗问题的精髓

查阅资料后,我了解到荷兰国旗问题的经典解法 ——三指针法

这种方法通过维护三个指针,将数组分为四个区域:

  1. 0 区域:[0, left)
  2. 1 区域:[left, curr)
  3. 未处理区域:[curr, right]
  4. 2 区域:(right, n-1]

 具体步骤如下:

初始化 left=0,curr=0,right=n-1 当 curr <= right 时:

        若 nums [curr] == 0,交换 nums [curr] 和 nums [left],left++,curr++

        若 nums [curr] == 1,curr++

        若 nums [curr] == 2,交换 nums [curr] 和 nums [right],right-- 这里的关键在于,

        当 nums [curr] == 2 时,交换后 curr 不移动,

        因为交换过来的元素可能是 0 或 2,需要再次检查。

六个人的排队逻辑

假设六个人的衣服颜色顺序为:
红、蓝、红、白、蓝、白
对应数组:nums = [0, 2, 0, 1, 2, 1](0 = 红,1 = 白,2 = 蓝)
目标:将队伍排成 红→白→蓝(0→1→2)。

三指针法的 “排队指挥” 过程

步骤 1:curr 指向第 1 人(红,0)

        操作:红队需要站左边,让第 1 人(红)和left指向的人(自己)交换(相当于不动)。

        结果left右移到位置 1,curr右移到位置 1。

        当前队列[0, 2, 0, 1, 2, 1]指针状态left=1curr=1right=5

步骤 2:curr 指向第 2 人(蓝,2)

        操作:蓝队需要站右边,让第 2 人(蓝)和right指向的第 6 人(白,1)交换。交换后队列:[0, 1, 0, 2, 2, 2](第 2 人和第 6 人交换)。

        结果right左移到位置 4,curr不移动(因为交换来的第 2 人现在是白,需要重新检查)。

        当前队列[0, 1, 0, 2, 2, 2]

        指针状态left=1curr=1right=4

步骤 3:curr 仍指向第 2 人(白,1)

        操作:白队(1)应在中间,无需移动,直接让curr右移到位置 2。

        当前队列[0, 1, 0, 2, 2, 2]

        指针状态left=1curr=2right=4

步骤 4:curr 指向第 3 人(红,0)

        操作:红队需要站左边,让第 3 人(红)和left指向的第 2 人(白,1)交换。交换后队列:[0, 0, 1, 2, 2, 2]

        结果left右移到位置 2,curr右移到位置 3。

        当前队列[0, 0, 1, 2, 2, 2]

        指针状态left=2curr=3right=4

步骤 5:curr 指向第 4 人(蓝,2)

        操作:蓝队需要站右边,让第 4 人(蓝)和right指向的第 5 人(蓝,2)交换(相当于不动)。

                结果right左移到位置 3,curr不移动(因为交换来的还是蓝,需要重新检查)。

当前队列[0, 0, 1, 2, 2, 2]

        指针状态left=2curr=3right=3

步骤 6:curr 指向第 4 人(蓝,2),此时curr == right

        操作:蓝队已在右边,right左移到位置 2,循环结束(curr=3 > right=2)。

        最终队列[0, 0, 1, 2, 2, 2],符合红→白→蓝的顺序!

实现该操作的代码:

while(mid <= right){if(nums[mid]== 0){int temp = 0;temp = nums[left];nums[left] = nums[mid];nums[mid] = temp;left++;mid++; }else if(nums[mid]==2){int temp = 0;temp = nums[right];nums[right] = nums[mid];nums[mid] = temp;right--;}else{mid++;}}

总结与收获

通过解决荷兰国旗问题,我有以下几点收获:

  1. 对于原地排序问题,指针操作是关键,合理设计指针可以大幅提高效率。
  2. 当问题涉及多个区域时,多指针法是一个值得尝试的方向。
  3. 处理指针问题时,一定要明确每个指针的含义和边界条件,避免越界和逻辑错误。
  4. 刷题不仅要追求 AC,还要深入理解解法背后的思想,做到举一反三。

http://www.xdnf.cn/news/7092.html

相关文章:

  • AM32电调学习解读七:其他代码文件介绍
  • 2901. 最长相邻不相等子序列 II
  • Seata源码—6.Seata AT模式的数据源代理一
  • 2025.05.17得物机考笔试真题第二题
  • React 19中useContext不需要Provider了。
  • Java基础知识总结(超详细整理)
  • 32LED心形灯程序源代码
  • 常见的 HTTP 接口(请求方法)
  • PCB设计(十九)PCB设计中NPN/PNP选型策略
  • Window远程连接Linux桌面版
  • 掘金欧洲宠物经济新蓝海:比利时天然宠粮市场爆发与跨境新机遇
  • c++从入门到精通(六)--特殊工具与技术-完结篇
  • Azure 机器学习初学者指南
  • Nacos数据写入流程
  • 深入理解EKS 工作节点的网络架构
  • Cadence学习笔记之---PCB器件放置与布局
  • SSM框架整合:从入门到实战
  • 大模型微调步骤整理
  • Flink CEP是什么?
  • 【数据结构与算法】ArrayList 与顺序表的实现
  • C++23 新特性:使某些视图的多参数构造函数显式化(P2711R1)
  • HBM的“暗战”
  • Spring AOP从0到1
  • STM32CubeMX生成UTF-8编码文件的设置方法
  • 第12章 Java多线程机制
  • 阶段四 项目1-苍穹外卖 第一章 Git
  • 基于matlab/simulink锂电池算法学习集合(SOC、SOH、BMS)
  • FloodFill算法:洪水般的图像处理艺术
  • #Redis黑马点评#(六)Redis当中的消息队列
  • 从0到1吃透卷积神经网络(CNN):原理与实战全解析