news 2026/10/7 5:16:02

【技巧】LC 75.颜色分类

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【技巧】LC 75.颜色分类

文章目录

  • 前言
  • 一、题目
    • 1、原题链接
    • 2、题目描述
  • 二、个人思路整理
    • 1、思路分析
    • 2、解题代码
  • 三、知识风暴

前言

本专栏文章为《LeetCode 热题 100》的刷题题解,相关内容如有侵权,立即删除。

一、题目

1、原题链接

75.颜色分类

2、题目描述


二、个人思路整理

1、思路分析

核心思路:三指针法/荷兰国旗算法
利用三个指针将数组划分为 4 个区间:

  • [0, p0):全为 0(红色)
  • [p0, i):全为 1(白色)
  • [i, p2]:未处理区域
  • (p2, n - 1]:全为 2(蓝色)

指针移动逻辑:
维护当前指针i(从 0 开始)以及边界指针p0 = 0和p2 = nums.size() - 1,循环条件为i <= p2:

  1. nums[i] == 0:
    • 与nums[p0]交换;
    • p0++,i++(因为交换过来的只可能是 1 或当前元素自身,不需要二次检查)。
  2. nums[i] == 1:
    • 属于中间区域,直接i++。
  3. nums[i] == 2:
    • 与nums[p2]交换;
    • p2--;
    • 注意:此时i不能自增,因为从p2换过来的元素尚未检查(可能是 0 或 2),下一轮循环需要继续判断当前的nums[i]。

2、解题代码

classSolution{public:voidsortColors(vector<int>&nums){// p0:0的最右边界(下一个0应该放置的位置,即 nums[0...p0-1] 全为0)// p2:2的最左边界(下一个2应该放置的位置,即 nums[p2+1...n-1] 全为2)intp0=0,p2=nums.size()-1;// i:当前遍历指针,维护 nums[p0...i-1] 全为 1inti=0;// 当 i > p2 时,说明未处理区间为空,排序完成while(i<=p2){if(nums[i]==0){// 遇到 0:与 p0 处的元素交换,放入左侧 0 区间swap(nums[i],nums[p0]);p0++;// 换过来的元素只可能是 1(当 p0 < i 时)或者就是当前的 0 (当 p0 == i 时)// 因此该位置已确认符合顺序,i 直接右移i++;}elseif(nums[i]==2){// 遇到2:与 p2 处的元素交换,放入右侧 2 区间swap(nums[i],nums[p2]);p2--;// 注意:此时换到 nums[i] 的元素尚未经过检验(可能是 0、1或2)// 因此 i 不能自增,下一轮循环需继续检查当前的 nums[i]}else{// 遇到 1:本身就处于中间区间,直接跳过i++;}}}};

复杂度分析

  • 时间复杂度:O ( n ) O(n)O(n),每个元素最多被交换/访问两次。
  • 空间复杂度:O ( 1 ) O(1)O(1),常数个变量空间占用。

三、知识风暴

三指针法(荷兰国旗算法)是本题的核心算法思想。它通过维护三个指针,将数组划分为 4 个区间,在一次遍历中完成所有元素的归位,从而以O ( n ) O(n)O(n)的时间复杂度高效求解。

算法核心思想:

  • 区间划分:利用p0、i、p2三个指针,将数组划分为「全 0 区」「全 1 区」「未处理区」「全 2 区」四个区间,每个元素只需被访问一次即可确定最终位置。
  • 指针移动:p0指向下一个 0 应放置的位置,p2指向下一个 2 应放置的位置,i为当前遍历指针。当i越过p2时,未处理区间为空,排序完成。
  • 与排序算法的区别:普通排序(如快速排序、归并排序)需要O ( n log ⁡ n ) O(n \log n)O(nlogn)的比较交换;而本题元素取值只有 0、1、2 三种,三指针法利用这一特性,将复杂度降到线性O ( n ) O(n)O(n),且空间复杂度为O ( 1 ) O(1)O(1)。

常见对比:三指针法 vs 计数排序

  • 三指针法:时间复杂度O ( n ) O(n)O(n),空间复杂度O ( 1 ) O(1)O(1)。只需一次遍历即可完成排序,且不需要额外数组,适合对数组进行原地排序的场景。
  • 计数排序:时间复杂度O ( n ) O(n)O(n),空间复杂度O ( k ) O(k)O(k)(k kk为取值种类数,本题k = 3 k=3k=3)。需要先统计各元素出现次数,再回填数组,代码更直观但需要额外空间。
  • 共同点:两者都能在线性时间内完成排序。区别在于三指针法通过交换实现原地排序,而计数排序依赖计数数组回填。

三指针法的设计思想:

  • 核心思想:把「排序」问题转化为「区间划分」问题——通过指针维护边界,让每个元素在遍历过程中直接落入正确区间,无需回溯。
  • 与本题的联系:颜色分类问题天然具有「三值」特性——每个元素只能是 0、1、2 之一。因此可以用三个指针分别维护 0 区右边界、1 区右边界、2 区左边界,一次遍历即可完成全部归位。
  • 注意事项:当nums[i] == 2时,与nums[p2]交换后i不能自增,因为换过来的元素可能是 0 或 2,需要下一轮继续判断;而当nums[i] == 0时,与nums[p0]交换后i可以直接自增,因为换过来的只可能是 1 或当前元素自身。

使用要点:

  • 指针初始化:p0 = 0,p2 = nums.size() - 1,i = 0,循环条件为i <= p2。
  • 交换逻辑:nums[i] == 0时与nums[p0]交换并p0++、i++;nums[i] == 2时与nums[p2]交换并p2--(i不自增);nums[i] == 1时直接i++。
  • 终止条件:当i > p2时,未处理区间为空,此时[0, p0)全为 0、[p0, i)全为 1、(p2, n-1]全为 2,排序完成。
  • 结果返回:排序在原数组上原地完成,无需返回值。

算法变体与扩展:

  • 移动零(LeetCode 283):本质是「双指针」的简化版,只区分 0 和非 0 两类元素,用快慢指针将非零元素前移、零元素后移。
  • 奇偶排序:将数组按奇偶性划分,与本题「按值划分」思路一致,可用双指针分别维护奇偶边界。
  • 三路快排(Quick Sort 3-way):快速排序在处理大量重复元素时的优化版本,正是借鉴了荷兰国旗算法的三指针思想,将数组划分为「小于」「等于」「大于」三个区间。

相关 LeetCode 例题:

  • 283. 移动零(双指针 + 区间划分)
  • 905. 按奇偶排序数组(双指针 + 奇偶划分)
  • 912. 排序数组(三路快排优化)
  • 215. 数组中的第 K 个最大元素(快速选择 + 分区思想)
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/7 5:15:54

Excel VBA:精准选取数据与批量移动行的实战指南

有段时间没写VBA实战类的内容了&#xff0c;今天正好借一个高频需求聊聊&#xff1a;Excel里“精准选取数据”和“把数据移动到目标位置”。这两个动作听着简单&#xff0c;但真正写起VBA来&#xff0c;坑不少。比如几千行数据里要挑出符合条件的记录&#xff0c;再搬到另一个表…

作者头像 李华
网站建设 2026/10/7 5:15:39

C语言PKCS#7填充实现:边界条件与安全陷阱详解

一个多星期前帮同事排查一个加解密模块的问题&#xff0c;现象很有意思&#xff1a;AES加密后的数据长度总是对不上块大小&#xff0c;解密出来末尾还有一堆莫名其妙的字节。查到最后&#xff0c;根子全在PKCS#7填充上——实现的人把“恰好整块不填充”这个细节搞错了。这件事让…

作者头像 李华
网站建设 2026/10/7 5:14:53

MCP协议实战指南:原理、接入场景与故障排查全解析

最近团队搭AI辅助开发环境&#xff0c;从Cursor、Codex到CherryStudio都试了一圈&#xff0c;工具没少换&#xff0c;最后发现所有人都在讨论同一个词&#xff1a;MCP。不管是让AI查项目代码、连Oracle数据库&#xff0c;还是把Figma设计稿直接拉给Codex当上下文&#xff0c;背…

作者头像 李华
网站建设 2026/10/7 5:14:33

Spectre与Meltdown:Coursebook乱序执行漏洞深度解析

Spectre与Meltdown&#xff1a;Coursebook乱序执行漏洞深度解析 【免费下载链接】coursebook Open Source Introductory Systems Programming Textbook for the University of Illinois 项目地址: https://gitcode.com/GitHub_Trending/co/coursebook Coursebook 是伊利…

作者头像 李华
网站建设 2026/10/7 5:14:03

Java 对接大模型流式接口:OpenAI 与 Anthropic 协议差异及适配实践

1. 为什么说 OpenAI 的接口协议是"普通话"第一次接触大模型接口对接的 Java 开发者&#xff0c;大概率是从 OpenAI 的/v1/chat/completions开始的。这个接口的请求体长这样&#xff1a;model、messages、stream、temperature&#xff0c;返回体里是choices[0].delta.…

作者头像 李华
网站建设 2026/10/7 5:13:35

中小型企业网络规划实战:VLAN、NAT、ACL与HSRP配置全解析

简介&#xff1a;一份关于中小型企业网络规划与设计的完整方案文档&#xff0c;面向需要搭建内部网络的企业IT人员、网络初学者及高校相关专业学生。内容以企业信息化需求为起点&#xff0c;系统梳理需求分析、Cisco设备选型、拓扑结构规划、网络安全设计与测试优化等关键环节&…

作者头像 李华