目录

1. 颜色分类

1.1 题目分析

1.2 解法

1.3 代码实现

2. 排序数组

2.1 题目解析

2.2 解法

2.3 代码实现


1. 颜色分类

75. 颜色分类 - 力扣(LeetCode)

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

我们使用整数 0、 1 和 2 分别表示红色、白色和蓝色。

    必须在不使用库内置的 sort 函数的情况下解决这个问题。

    示例 1:

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

    示例 2:

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

    提示:

    • n == nums.length
    • 1 <= n <= 300
    • nums[i] 为 01 或 2

    1.1 题目分析

    题目本质
    只有三种取值 0/1/2,要求原地按 0→1→2 排序。可抽象为:一次扫描把元素分到三个“桶/分区”。

    常规解法

    • 计数法:统计 0/1/2 的数量,再回写。时间 O(n),空间 O(1),两趟且缺少“原地一次遍历”的训练价值。

    • 直接排序:不允许用库排序,且会是 O(n log n)。

    问题分析
    若用交换排序或冒泡都会超过 O(n)。想在 O(n) 一趟里完成,必须让每次访问都把当前元素“扔到正确区域”,并保持区间边界稳定(循环不变式),这就是“荷兰国旗”思想。

    思路转折
    维护三指针把数组动态分成 4 段(不变式):

    • 0..left-1 全是 0

    • left..i-1 全是 1

    • i..right 还未处理

    • right+1..n-1 全是 2
      指针 i 扫描未处理区:遇到 0 扔到左边,遇到 2 扔到右边,遇到 1 跳过。直到 i > right 结束

    1.2 解法

    算法思想

    三指针分区(Dutch National Flag):

    • ↦ 与 left 交换,left++,i++

    • 1 ↦ i++

    • 2 ↦ 与 right 交换,right--,i 不动(因为换来的元素未检查)

    i)初始化:left=0, right=n-1, i=0。

    ii)循环 i <= right:

    • nums[i]==0:交换到左区,扩左界并前进 i;

    • nums[i]==2:交换到右区,收缩右界,但不移动 i;

    • nums[i]==1:仅 i++。

    iii)循环结束时四段不变式成立,数组即为 0…0 1…1 2…2。

    小解释:为什么 0 情况可以 i++,而 2 情况不能

    • 0 情况:left 永远 ≤ i。交换把 0 放到最左侧,nums[i] 会变成原来 left 位置的元素(已处理区的 1),可以直接前进。

    • 2 情况:right 在 i 右边,交换把一个未知元素换到 i,必须继续判断它,所以 不能 i++

    1.3 代码实现

    代码实现(写法一:直观边界 i <= right)

    class Solution {private void swap(int[] a, int i, int j) {int t = a[i]; a[i] = a[j]; a[j] = t;}public void sortColors(int[] nums) {int n = nums.length;int left = 0, right = n - 1; // 左右“投放位”for (int i = 0; i <= right; ) {if (nums[i] == 0) {swap(nums, left, i);left++; i++;             // 换来的一定在[0,left)或[1区],无需再查} else if (nums[i] == 2) {swap(nums, right, i);right--;                 // 换来的未知,i不动,继续检查当前位置} else { // nums[i] == 1i++;}}}
    }
    

    代码实现(写法二:i < right,left=-1,right=n)

    class Solution {private void swap(int[] a, int i, int j) {int t = a[i]; a[i] = a[j]; a[j] = t;}public void sortColors(int[] nums) {int left = -1, right = nums.length, i = 0;while (i < right) {if (nums[i] == 0)       swap(nums, ++left, i++); // 左区扩张else if (nums[i] == 1)  i++;                     // 中区自然累积else                    swap(nums, --right, i);  // 右区收缩,i不动}}
    }
    

    复杂度分析

    • 时间复杂度:O(n)(每个元素最多被交换/访问常数次)

    • 空间复杂度:O(1)(原地修改,仅常数指针)

    2. 排序数组

    912. 排序数组 - 力扣(LeetCode)

    给你一个整数数组 nums,请你将该数组升序排列。

    你必须在 不使用任何内置函数 的情况下解决问题,时间复杂度为 O(nlog(n)),并且空间复杂度尽可能小。

      示例 1:

      输入:nums = [5,2,3,1]
      输出:[1,2,3,5]
      解释:数组排序后,某些数字的位置没有改变(例如,2 和 3),而其他数字的位置发生了改变(例如,1 和 5)。
      

      示例 2:

      输入:nums = [5,1,1,2,0,0]
      输出:[0,0,1,1,2,5]
      解释:请注意,nums 的值不一定唯一。

      提示:

      • 1 <= nums.length <= 5 * 104
      • -5 * 104 <= nums[i] <= 5 * 104

      2.1 题目解析

      题目本质
      把整型数组升序排列;目标是平均 O(n log n),并尽量原地。数据范围允许重复与负数。

      常规解法

      • 归并排序:时间稳定 O(n log n),但需要 O(n) 额外空间。

      • 快速排序:平均 O(n log n)、原地;若选取随机基准 + 三路划分,对大量重复值更友好。

      问题分析

      • 经典双路快排在重复元素多时会退化,划分不均,递归层次加深。

      • 三路划分把数组维护为三段:< key、= key、> key,一次扫描就把等于段“压缩”出来,递归只落在两侧,更稳定。

      思路转折(不变式引导)
      在子数组 [l, r] 内维护指针 left/i/right,保持不变式:

      • [l, left] < key

      • [left+1, i-1] = key

      • [i, rgiht-1] 未处理

      • [right, r] > key

      • 循环扫描未处理区:
        a[i] < key → 交换到左边 swap(++lt, i++)
        a[i] == key→ i++
        a[i] > key→ 交换到右边 swap(--gt, i)(i 不动,因新换来的还未判断)
        当 i == right,未处理区为空,递归排序 < key的 [l,left] 与 > key的 [right, r] 两端。

      2.2 解法

      算法思想

      • 随机基准:降低恶劣输入导致的退化概率;

      • 三路划分:一次扫描把等于段“吃掉”,递归只落两端;

      • 原地交换:常数额外空间。

      i)递归基:if (l >= r) return;

      ii)选择基准:key= nums[new Random().nextInt(r-l+1) + l]

      iii)运行三路划分循环,维持不变式。

      iiii)递归处理 [l, left] 与 [right, r]。

      iiiii)结束

      容易踩坑点:

      • 比较方向:a[i] < key 放左边;a[i] > key 放右边

      • 递归基:if (l >= r) return;

      • i 的移动:放左 i++;放右 不要 i++;等于 i++。

      • 边界名分清:l/r(递归区间)
        l / r:当前递归处理的子数组边界(闭区间)。
        left/right/i:划分指针,lt = l-1, i = l, gt = r+1

      • key:数值(从 [l, r] 随机取出的元素的值);不是索引。 复杂度分析

      2.3 代码实现

      import java.util.concurrent.ThreadLocalRandom;class Solution {private void swap(int[] a, int i, int j) {int t = a[i]; a[i] = a[j]; a[j] = t;}public int[] sortArray(int[] nums) {qsort(nums, 0, nums.length - 1);return nums;}private void qsort(int[] nums, int l, int r) {if (l >= r) return; // 递归基// 随机基准,降低退化概率int key = nums[new Random().nextInt(r-l+1) + l];int left = l - 1, i = l, right = r + 1;// 不变式:// [l, left]     < key// [left+1, i-1] = key// [i, right-1]   未处理// [right, r]     > keywhile (i < right) {if (nums[i] < key ) {swap(nums, ++left, i++);} else if (nums[i] > key ) {swap(nums, --right, i);   // i 不动:换来的还未检查} else {i++;}}// 递归两端;等于 key 的中段 [left+1, right-1] 已就位qsort(nums, l, left);qsort(nums, right, r);}
      }
      

      复杂度分析

      • 时间复杂度:期望 O(n log n);最差 O(n^2)(随机化可将概率降到极低)。

      • 空间复杂度:原地划分 O(1) 额外空间,整体为递归栈 O(log n)(期望)

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

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

      相关文章

      学习一下动调

      [NSSCTF 2nd]MyBasedie查一下用ida64打开main函数里面没有什么信息&#xff0c;接着追一下函数&#xff0c;内容在test函数里面函数会对我们输入的内容进行base64加密&#xff0c;这段逻辑也很简单&#xff0c;就是将加密后的字符串和目标字符串依次进行比较&#xff0c;一样就…

      Java试题-选择题(22)

      Java试题-选择题&#xff08;22&#xff09; 题目以下对JDBC事务描述错误的是 &#xff1f; A) JDBC事务属于JAVA事务的一种 B) JDBC事务属于容器事务类型 C) JDBC事务可以保证操作的完整性和一致性 D) JDBC事务是由Connection发起的&#xff0c;并由Connection控制要通过可滚动…

      蓝牙5.3核心技术架构解析:从控制器到主机的无线通信设计

      蓝牙5.3核心技术架构解析&#xff1a;从控制器到主机的无线通信设计在无线通信领域&#xff0c;蓝牙技术如何通过精巧的架构设计实现设备间的高效互操作&#xff1f;答案在于其分层架构与标准化的接口定义。蓝牙5.3核心规范作为现代无线通信的重要标准&#xff0c;其系统架构设…

      android View#performClick() 和 View#callOnClick() 的差异

      文章目录performClick()callOnClick()关键区别对比总结在 Android 中&#xff0c;View.performClick() 和 View.callOnClick() 都是用于触发视图点击事件的方法&#xff0c;但它们的设计目的和执行逻辑存在细微差异&#xff0c;具体区别如下&#xff1a;performClick() 核心作…

      PHP单独使用phinx使用数据库迁移

      可以独立使用的迁移包对比后&#xff0c;感觉phinx更接近PHP的使用习惯。 为什么要单独用&#xff1f; 因为我不想数据库的迁移文件依赖于某种框架。本来是可以在框架里直接安装这个包的&#xff0c;但是发现这个包依赖cakephp&#xff0c;而cakephp的函数与thinkphp的env()函…

      从零开始学习单片机18

      使用STM32CubeMX创建工程选择对应芯片后创建工程&#xff0c;首先设置时钟源内部时钟源包括LSI&#xff08;低速时钟&#xff09;和HSI&#xff08;高速时钟&#xff09;&#xff0c;使用内部时钟源就需要将图中的一二处勾选HCLK是芯片运行时的评率&#xff0c;虽然下面标的最大…

      如何使用 DeepSeek 帮助自己的工作?

      技术文章大纲&#xff1a;利用 DeepSeek 提升工作效率 了解 DeepSeek 的基本功能 DeepSeek 的核心能力&#xff1a;文本生成、代码辅助、数据分析支持的平台与访问方式&#xff08;网页端/API/集成工具&#xff09;适用场景&#xff1a;技术文档撰写、自动化流程设计、数据处理…

      计算机毕设javayit商城 基于SSM框架的校园二手交易全流程管理系统设计与实现 Java+MySQL的校园二手商品交易与供需对接平台开发

      计算机毕设 javayit 商城uwd1i9 &#xff08;配套有源码 程序 mysql数据库 论文&#xff09;本套源码可以先看具体功能演示视频领取&#xff0c;文末有联xi 可分享随着校园二手物品流通需求增长&#xff0c;传统校园二手交易依赖线下摆摊、社群发布的模式&#xff0c;存在信息分…

      Java函数式编程之【流(Stream)性能优化】

      Java函数式编程之【流&#xff08;Stream&#xff09;性能优化一、流&#xff08;Stream&#xff09;性能优化的预备知识&#xff08;一&#xff09;并行与并发的区别&#xff08;二&#xff09;Stream操作特性分类&#xff08;三&#xff09;Stream流管道的相关知识二、流&…

      Cybero: 1靶场渗透

      Cybero: 1 来自 <Cybero: 1 ~ VulnHub> 1&#xff0c;将两台虚拟机网络连接都改为NAT模式 2&#xff0c;攻击机上做namp局域网扫描发现靶机 nmap -sn 192.168.23.0/24 那么攻击机IP为192.168.23.128&#xff0c;靶场IP192.168.23.139 3&#xff0c;对靶机进行端口服务探…

      【学习笔记】非异步安全函数(禁止在信号处理中调用)

      非异步安全函数&#xff08;禁止在信号处理中调用&#xff09; 一、测试 在信号处理函数&#xff08;Signal Handler&#xff09;中&#xff0c;只有异步信号安全函数&#xff08;async-signal-safe functions&#xff09; 可以安全调用。这类函数的特点是&#xff1a;不使用全…

      【K8s】整体认识K8s之K8s的控制器

      作用&#xff1a;控制器的作用就是持续监控k8s集群的状态&#xff0c;让它处于我们期望的状态&#xff0c;常见的控制器有replicaset、deployment、daemonset、statefulset 、job 、cronjobReplicaset控制一组pod的副本数&#xff0c;始终与预设的值相同&#xff0c;会持续监视…

      R ggplot2学习Nature子刊一张图,换数据即可用!

      本次使用R语言复现Nature Communications上的1张组合图,这张图兼具颜值+节约版面! Fig. 1 b原图 ❤️复现效果图-b图❤️ ✅读入测试数据! ✅关键代码, # 关键代码 library(ggplot2) library(dplyr) library(cowplot)# --- 外圈图 --- p_outer <- ggplot(data_aug, aes…

      迷你电脑用到什么型号的RJ45网口

      迷你电脑常用的 RJ45 网口主要有标准 RJ45 网口和 Mini RJ45 网口两种。标准 RJ45 网口是最常见的类型&#xff0c;遵循 IEEE 802.3i 标准&#xff0c;采用 8P8C&#xff08;8 Position 8 Contact&#xff0c;8 位 8 触点&#xff09;连接器&#xff0c;有 T568A 和 T568B 两种…

      网络安全 | 保护智能家居和企业IoT设备的安全策略

      网络安全 | 保护智能家居和企业IoT设备的安全策略 一、前言 二、智能家居和企业 IoT 设备面临的安全威胁 2.1 设备自身安全缺陷 2.2 网络通信安全隐患 2.3 数据隐私风险 2.4 恶意软件和攻击手段 三、保护智能家居和企业 IoT 设备的安全策略 3.1 设备安全设计与制造环节的考量 3…

      优化器全指南:从原理到调优实战

      本文将带你轻松理解深度学习中的“导航系统”——优化器。我们会避开复杂的数学公式,用大量的比喻和图示,让你彻底明白 Adam、AdamW、LAMB 是怎么回事,并学会如何调节它们的关键参数。 第一部分:核心概念:优化器是什么? 一个简单的比喻: 想象你在一座大雾弥漫的山里(…

      Notepad++使用技巧1

      1.打开官方参考代码经常看到下图这种行尾很多空格的代码&#xff0c;一点都不合符华为的书写规范&#xff0c;阅读起来容易让人烦躁不安。初学者建议看看华为的代码书写规范&#xff0c;你将少走很多弯路&#xff0c;终生受益。2.快速去掉行尾很多空格方法点击顶部菜单栏“宏”…

      AIoT云边协同方式

      随着物联网&#xff08;IoT&#xff09;与人工智能&#xff08;AI&#xff09;的深度融合&#xff0c;AIoT&#xff08;人工智能物联网&#xff09;作为一种新兴技术范式&#xff0c;正在推动智能设备与产业的快速发展。AIoT通过云边协同的方式&#xff0c;将边缘侧的IoT设备、…

      MIT 6.5840 (Spring, 2024) 通关指南——Lab 1: MapReduce

      MIT 6.5840 (Spring, 2024) – Lab 1: MapReduce &#x1f468;‍&#x1f4bb; Charles &#x1f517; 实验手册&#xff1a; 6.5840 Lab 1: MapReduce &#x1f4c3; MapReduce 论文原文&#xff1a; mapreduce-osdi04.pdf ✍️ 本系列前文&#xff1a; MIT 6.5840 (Spring, …

      吴恩达机器学习作业五:神经网络正向传播

      数据集在作业一正向传播正向传播&#xff08;Forward Propagation&#xff09;是神经网络计算过程中的核心步骤&#xff0c;指的是将输入数据通过神经网络的各层依次传递&#xff0c;最终得到输出结果的过程。核心原理在神经网络中&#xff0c;信息从输入层流入&#xff0c;经过…