LeetCode 75. 颜色分类 - 双指针法高效解决(Java实现)

文章目录

    • 问题描述
    • 算法思路:三指针分区法
      • 核心思想
      • 指针定义
    • Java实现
    • 算法执行流程
    • 关键问题解析:为什么交换0后不需要重新检查?
      • 交换0时的两种情况分析
      • 详细解释:
    • 复杂度分析
    • 示例演示(输入:[2,0,2,1,1,0])
    • 总结

本文介绍一种时间复杂度O(n)、空间复杂度O(1)的优雅解法,通过双指针技术实现颜色分类的一趟扫描排序

问题描述

给定一个包含红色(0)、白色(1)和蓝色(2)的数组 nums,原地对它们进行排序,使得相同颜色的元素相邻,并按照红色、白色、蓝色的顺序排列。

示例:

输入:nums = [2,0,2,1,1,0]
输出:[0,0,1,1,2,2]

算法思路:三指针分区法

核心思想

使用三个指针将数组分为四个区域:

  1. [0, p0):已排序的0区域
  2. [p0, curr):已排序的1区域
  3. [curr, p2]:待处理区域
  4. (p2, end]:已排序的2区域

指针定义

  • p0:指向下一个0应放置的位置(0区域的右边界)
  • p2:指向下一个2应放置的位置(2区域的左边界)
  • curr:当前遍历指针,负责处理元素交换

Java实现

class Solution {public void sortColors(int[] nums) {if (nums == null || nums.length < 2) return;int p0 = 0;                   // 0区域右边界int p2 = nums.length - 1;     // 2区域左边界int curr = 0;                 // 当前遍历指针while (curr <= p2) {switch (nums[curr]) {case 0:// 将0交换到0区域swap(nums, curr++, p0++);break;case 1:// 1保留在中间区域curr++;break;case 2:// 将2交换到2区域swap(nums, curr, p2--);// 注意:curr不自增,需检查交换来的新元素break;}}}// 辅助交换函数private void swap(int[] nums, int i, int j) {int temp = nums[i];nums[i] = nums[j];nums[j] = temp;}
}

算法执行流程

  1. 初始化指针

    • p0 = 0(0区域起始位置)
    • p2 = nums.length-1(2区域起始位置)
    • curr = 0(从数组开头遍历)
  2. 元素处理逻辑

    • 遇到0:与p0交换,p0curr右移
    • 遇到1:跳过,curr右移
    • 遇到2:与p2交换,p2左移(curr不变)
  3. 终止条件curr > p2(所有元素处理完毕)

关键问题解析:为什么交换0后不需要重新检查?

交换0时的两种情况分析

情况条件交换前状态交换后状态
情况1curr > p0nums[p0] = 1nums[curr] = 1
情况2curr == p0自身交换保持不变

详细解释:

  1. curr > p0

    • p0位置必定是1(因为0区域和1区域已排序)
    • 交换后curr位置变为1 → 可直接跳过处理(1属于中间区域)
  2. curr == p0

    • 自身交换无实际变化
    • 元素保持0 → 属于已排序区域

结论:交换0后curr位置的新元素只可能是0或1,都无需再次处理,因此可以直接移动curr指针。

复杂度分析

指标说明
时间复杂度O(n)单次遍历完成排序
空间复杂度O(1)仅使用常数级额外空间

示例演示(输入:[2,0,2,1,1,0])

步骤操作数组状态指针变化
1初始状态[2,0,2,1,1,0]p0=0, p2=5, curr=0
2处理2:交换curr↔p2[0,0,2,1,1,2]p2=4
3处理0:交换curr↔p0[0,0,2,1,1,2]p0=1, curr=1
4处理0:交换curr↔p0[0,0,2,1,1,2]p0=2, curr=2
5处理2:交换curr↔p2[0,0,1,1,2,2]p2=3
6处理1:跳过[0,0,1,1,2,2]curr=3
7处理1:跳过[0,0,1,1,2,2]curr=4 > p2(结束)

总结

双指针法解决颜色分类问题的核心在于:

  1. 通过p0p2维护已排序区域
  2. curr指针动态处理待排序区域
  3. 巧妙利用交换操作实现元素归位
  4. 利用数组分区特性优化操作步骤(交换0后无需重检)

该算法是荷兰国旗问题的经典解法,体现了双指针技术在数组原地操作中的高效性,是面试中的高频考点。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.pswp.cn/bicheng/82942.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【MySQL】C语言连接

要使用C语言连接mysql&#xff0c;需要使用mysql官网提供的库&#xff0c;大家可以去官网下载 我们使用C接口库来进行连接 要正确使用&#xff0c;我们需要做一些准备工作: 保证mysql服务有效在官网上下载合适自己平台的mysql connect库&#xff0c;以备后用 下载开发库 s…

NFS 挂载配置与优化最佳实践指南

文章目录 NFS 挂载配置与优化最佳实践指南1. 服务器端配置1.1 安装 NFS 服务1.2 配置共享目录常用配置选项说明 1.3 启动与检查服务 2. 客户端挂载2.1 安装 NFS 客户端2.2 挂载 NFS 共享2.3 自动挂载 3. 客户端挂载选项4. 性能优化与故障排查4.1 性能优化建议4.2 常见问题排查 …

3D PDF如何制作?SOLIDWORKS MBD模板定制技巧

SOLIDWORKS制作3D PDF模版 SOLIDWORKS MBD能够帮助工程师以清晰直观的方式描述产品尺寸信息。在3D PDF文件中&#xff0c;用户可以自由旋转和移动视图&#xff0c;方便查看模型的各个尺寸细节。 本文将带您一步步学习如何使用SOLIDWORKS MBD制作专业的3D PDF模板&#xff0c;…

Unity-QFramework框架学习-MVC、Command、Event、Utility、System、BindableProperty

QFramework QFramework简介 QFramework是一套渐进式、快速开发框架&#xff0c;适用于任何类型的游戏及应用项目&#xff0c;它包含一套开发架构和大量的工具集 QFramework的特性 简洁性&#xff1a;QFramework 强调代码的简洁性和易用性&#xff0c;让开发者能够快速上手&a…

R3GAN训练自己的数据集

简介 简介&#xff1a;这篇论文挑战了"GANs难以训练"的广泛观点&#xff0c;通过提出一个更稳定的损失函数和现代化的网络架构&#xff0c;构建了一个简洁而高效的GAN基线模型R3GAN。作者证明了通过合适的理论基础和架构设计&#xff0c;GANs可以稳定训练并达到优异…

【PhysUnits】15.1 引入P1后的加一特质(add1.rs)

一、源码 代码实现了类型系统中的"加一"操作&#xff08;Add1 trait&#xff09;&#xff0c;用于在编译期进行数字的增量计算。 //! 加一操作特质实现 / Increment operation trait implementation //! //! 说明&#xff1a; //! 1. Z0、P1,、N1 1&#xff0…

记录算法笔记(2025.5.29)最小栈

设计一个支持 push &#xff0c;pop &#xff0c;top 操作&#xff0c;并能在常数时间内检索到最小元素的栈。 实现 MinStack 类: MinStack() 初始化堆栈对象。void push(int val) 将元素val推入堆栈。void pop() 删除堆栈顶部的元素。int top() 获取堆栈顶部的元素。int get…

Android高级开发第一篇 - JNI(初级入门篇)

文章目录 Android高级开发JNI开发第一篇&#xff08;初级入门篇&#xff09;&#x1f9e0; 一、什么是 JNI&#xff1f;✅ 为什么要用 JNI&#xff1f; ⚙️ 二、开发环境准备开发工具 &#x1f680; 三、创建一个支持 JNI 的 Android 项目第一步&#xff1a;创建新项目项目结构…

PyTorch Image Models (timm) 技术指南

timm PyTorch Image Models (timm) 技术指南功能概述 一、引言二、timm 库概述三、安装 timm 库四、模型加载与推理示例4.1 通用推理流程4.2 具体模型示例4.2.1 ResNeXt50-32x4d4.2.2 EfficientNet-V2 Small 模型4.2.3 DeiT-3 large 模型4.2.4 RepViT-M2 模型4.2.5 ResNet-RS-1…

openEuler安装MySql8(tar包模式)

操作系统版本&#xff1a; openEuler release 22.03 (LTS-SP4) MySql版本&#xff1a; 下载地址&#xff1a; https://dev.mysql.com/downloads/mysql/ 准备安装&#xff1a; 关闭防火墙&#xff1a; 停止防火墙 #systemctl stop firewalld.service 关闭防火墙 #systemc…

从零开始的数据结构教程(六) 贪心算法

&#x1f36c; 标题一&#xff1a;贪心核心思想——发糖果时的最优分配策略 贪心算法 (Greedy Algorithm) 是一种简单直观的算法策略。它在每一步选择中都采取在当前状态下最好或最优&#xff08;即最有利&#xff09;的选择&#xff0c;从而希望得到一个全局最优解。这就像你…

CPP中CAS std::chrono 信号量与Any类的手动实现

前言 CAS&#xff08;Compare and Swap&#xff09; 是一种用于多线程同步的原子指令。它通过比较和交换操作来确保数据的一致性和线程安全性。CAS操作涉及三个操作数&#xff1a;内存位置V、预期值E和新值U。当且仅当内存位置V的值与预期值E相等时&#xff0c;CAS才会将内存位…

Axure设计案例——科技感对比柱状图

想让数据对比展示摆脱平淡无奇&#xff0c;瞬间抓住观众的眼球吗&#xff1f;那就来看看这个Axure设计的科技感对比柱状图案例&#xff01;科技感设计风格运用独特元素打破传统对比柱状图的常规&#xff0c;营造出一种极具冲击力的视觉氛围。每一组柱状体都仿佛是科技战场上的士…

怒更一波免费声音克隆和AI配音功能

宝子们&#xff01; 最近咱软件TransDuck的免费声音克隆和AI配音功能被大家用爆啦&#xff01;感谢各位自来水疯狂安利&#xff01;&#xff01; DD这里也是收到好多用户提的宝贵建议&#xff01;所以&#xff0c;连夜肝了波更新&#xff01; 这次重点更新使用克隆音色进行A…

UDP协议原理与Java编程实战:无连接通信的奥秘

1.UDP协议核心原理 1. 无连接特性&#xff1a;快速通信的基石 UDP&#xff08;User Datagram Protocol&#xff0c;用户数据报协议&#xff09;是TCP/IP协议族中无连接的轻量级传输层协议。与TCP的“三次握手”建立连接不同&#xff0c;UDP通信无需提前建立链路&#xff0c;发送…

vue-seamless-scroll 结束从头开始,加延时后滚动

今天遇到一个大屏需求&#xff1a; 1️⃣初始进入页面停留5秒&#xff0c;然后开始滚动 2️⃣最后一条数据出现在最后一行时候暂停5秒&#xff0c;然后返回1️⃣ 依次循环&#xff0c;发现vue-seamless-scroll的方法 ScrollEnd是监测最后一条数据消失在第一行才回调&#xff…

[Protobuf] 快速上手:安全高效的序列化指南

标题&#xff1a;[Protobuf] (1)快速上手 水墨不写bug 文章目录 一、什么是protobuf&#xff1f;二、protobuf的特点三、使用protobuf的过程&#xff1f;1、定义消息格式&#xff08;.proto文件&#xff09;(1)指定语法版本(2)package 声明符 2、使用protoc编译器生成代码&…

uniapp调用java接口 跨域问题

前言 之前在Windows10本地 调试一个旧项目&#xff0c;手机移动端用的是Uni-app&#xff0c;vue的版本是v2。后端是java spring-boot。运行手机移动端的首页请求后台接口老是提示错误信息。 错误信息如下&#xff1a; Access to XMLHttpRequest at http://localhost:8080/api/…

[ Qt ] | Qlabel使用

目录 属性 setTextFormat 插入图片 设置图片根据窗口大小实时变化 边框和对其方式 ​编辑 设置缩进 设置伙伴 Qlabel可以用来显式图片和文字 属性 text textFormat Qlabel独有的机制&#xff1a;buddy setTextFormat 插入图片 设置图片根据窗口大小实时变化 Qt中表…

Springboot 项目一启动就获取HttpSession

在 Spring Boot 项目中&#xff0c;HttpSession 是有状态的&#xff0c;通常只有在用户发起 HTTP 请求并建立会话后才会创建。因此&#xff0c;在项目启动时&#xff08;即应用刚启动还未处理任何请求&#xff09;是无法获取到 HttpSession 的。 方法一&#xff1a;使用 HttpS…