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

LeetCode 912:排序数组 | 排序算法全面解析

LeetCode 912排序数组 | 排序算法全面解析引言排序数组Sort an Array是 LeetCode 第 912 题难度为 Medium。题目要求将给定数组排序并返回。虽然这是一个看似简单的问题但题目对时间和空间复杂度有要求需要我们实现各种排序算法并分析其性能特点。排序是计算机科学中最基础的问题之一也是面试中的高频考点。本文将全面解析各种排序算法包括冒泡排序、选择排序、插入排序、归并排序、快速排序、堆排序等分析它们的时间复杂度、空间复杂度和稳定性特点。排序算法分类排序算法 Overview排序算法可以分为两大类比较排序和非比较排序。比较排序通过比较元素之间的大小关系来确定顺序而非比较排序不通过比较来排序。比较排序的时间复杂度下界是 O(n log n)而非比较排序可以达到 O(n)。但非比较排序对待排序数据有特殊要求如计数排序要求数据范围已知且不太大。常见排序算法常见排序算法包括O(n²) 冒泡排序、选择排序、插入排序O(n log n) 归并排序、快速排序、堆排序O(n) 计数排序、桶排序、基数排序冒泡排序算法原理冒泡排序是最简单的排序算法之一。它重复地遍历数组比较相邻的两个元素如果顺序错误就交换。通过多次遍历最终使数组有序。def bubble_sort(nums): n len(nums) for i in range(n): swapped False for j in range(0, n - i - 1): if nums[j] nums[j 1]: nums[j], nums[j 1] nums[j 1], nums[j] swapped True if not swapped: break return nums冒泡排序的名称来源于算法执行过程中较小的元素逐渐冒泡到数组顶端的过程。复杂度分析时间复杂度最好 O(n)最坏 O(n²)平均 O(n²)空间复杂度O(1)稳定性稳定冒泡排序的最好情况是数组已经有序只需要一次遍历就能检测到没有交换从而提前终止。选择排序算法原理选择排序首先在未排序序列中找到最小或最大元素放到排序序列的起始位置然后从剩余未排序序列中继续寻找最小或最大元素放到已排序序列的末尾。def selection_sort(nums): n len(nums) for i in range(n): min_idx i for j in range(i 1, n): if nums[j] nums[min_idx]: min_idx j nums[i], nums[min_idx] nums[min_idx], nums[i] return nums复杂度分析时间复杂度O(n²)最好和最坏都是空间复杂度O(1)稳定性不稳定选择排序的不稳定性来源于它可能改变相同元素的相对位置。例如在 [2, 2, 1] 中第一次会选择 1 与第一个 2 交换导致相同元素的相对顺序改变。插入排序算法原理插入排序类似于整理扑克牌的过程。将数组分为已排序和未排序两部分每次从未排序部分取出一个元素在已排序部分找到合适的位置插入。def insertion_sort(nums): for i in range(1, len(nums)): key nums[i] j i - 1 while j 0 and nums[j] key: nums[j 1] nums[j] j - 1 nums[j 1] key return nums复杂度分析时间复杂度最好 O(n)最坏 O(n²)平均 O(n²)空间复杂度O(1)稳定性稳定插入排序在数组基本有序时效率很高因为只需要很少的移动操作。在实际排序中插入排序经常与其他排序算法结合使用如快速排序的小数组排序阶段。归并排序算法原理归并排序采用分治法思想。将数组递归地分成两半分别排序后合并。由于需要合并两个有序数组需要额外的 O(n) 空间。def merge_sort(nums): if len(nums) 1: return nums mid len(nums) // 2 left merge_sort(nums[:mid]) right merge_sort(nums[mid:]) return merge(left, right) def merge(left, right): result [] i j 0 while i len(left) and j len(right): if left[i] right[j]: result.append(left[i]) i 1 else: result.append(right[j]) j 1 result.extend(left[i:]) result.extend(right[j:]) return result复杂度分析时间复杂度O(n log n)最好、最坏、平均都是空间复杂度O(n)稳定性稳定归并排序的缺点是需要额外的 O(n) 空间但优点是稳定性好且在外部排序数据量太大无法一次性放入内存中有重要应用。快速排序算法原理快速排序同样采用分治法。首先选择一个基准元素pivot将数组分为两部分小于 pivot 的元素和大于 pivot 的元素。然后递归地对两部分进行排序。def quick_sort(nums): if len(nums) 1: return nums pivot nums[len(nums) // 2] left [x for x in nums if x pivot] middle [x for x in nums if x pivot] right [x for x in nums if x pivot] return quick_sort(left) middle quick_sort(right)原地版本的快速排序更加空间高效def quick_sort_inplace(nums, low0, highNone): if high is None: high len(nums) - 1 if low high: pivot_idx partition(nums, low, high) quick_sort_inplace(nums, low, pivot_idx - 1) quick_sort_inplace(nums, pivot_idx 1, high) def partition(nums, low, high): pivot nums[high] i low - 1 for j in range(low, high): if nums[j] pivot: i 1 nums[i], nums[j] nums[j], nums[i] nums[i 1], nums[high] nums[high], nums[i 1] return i 1复杂度分析时间复杂度最好 O(n log n)最坏 O(n²)平均 O(n log n)空间复杂度O(log n)递归栈稳定性不稳定快速排序的最坏情况发生在数组已经有序或完全逆序时。为避免最坏情况通常采用随机选择基准或三数取中法。堆排序算法原理堆排序使用二叉堆数据结构。首先将数组构建成最大堆然后反复提取最大元素并调整堆。import heapq def heap_sort(nums): heapq.heapify(nums) return [heapq.heappop(nums) for _ in range(len(nums))]原地版本的堆排序def heap_sort_inplace(nums): n len(nums) def heapify(nums, n, i): largest i left 2 * i 1 right 2 * i 2 if left n and nums[left] nums[largest]: largest left if right n and nums[right] nums[largest]: largest right if largest ! i: nums[i], nums[largest] nums[largest], nums[i] heapify(nums, n, largest) for i in range(n // 2 - 1, -1, -1): heapify(nums, n, i) for i in range(n - 1, 0, -1): nums[0], nums[i] nums[i], nums[0] heapify(nums, i, 0) return nums复杂度分析时间复杂度O(n log n)最好、最坏、平均都是空间复杂度O(1)稳定性不稳定堆排序的优点是不论输入数据如何时间复杂度都是 O(n log n)且是原地排序。缺点是缓存命中率和实际运行常数可能不如快速排序。计数排序算法原理计数排序是一种非比较排序适用于范围不大的整数排序。统计每个元素出现的次数然后根据计数将元素放回原数组。def counting_sort(nums): if not nums: return nums min_val, max_val min(nums), max(nums) count [0] * (max_val - min_val 1) for num in nums: count[num - min_val] 1 result [] for i, c in enumerate(count): result.extend([i min_val] * c) return result复杂度分析时间复杂度O(n k)其中 k 是数据范围空间复杂度O(k)稳定性稳定需要额外处理计数排序在数据范围不大时非常高效可以达到线性时间复杂度。算法对比时间复杂度对比算法最好最坏平均冒泡排序O(n)O(n²)O(n²)选择排序O(n²)O(n²)O(n²)插入排序O(n)O(n²)O(n²)归并排序O(n log n)O(n log n)O(n log n)快速排序O(n log n)O(n²)O(n log n)堆排序O(n log n)O(n log n)O(n log n)计数排序O(n k)O(n k)O(n k)空间复杂度对比算法空间复杂度冒泡排序O(1)选择排序O(1)插入排序O(1)归并排序O(n)快速排序O(log n)堆排序O(1)计数排序O(k)稳定性对比稳定排序冒泡排序、插入排序、归并排序、计数排序不稳定排序选择排序、快速排序、堆排序总结排序算法是算法学习的基础。不同排序算法有各自的优缺点适用于不同场景数据基本有序时插入排序效率最高需要稳定排序时归并排序是首选通用场景下快速排序通常是最佳选择数据范围已知且不大时计数排序可以达到线性时间理解各种排序算法的原理、复杂度和特点对于提升算法能力和应对面试都有重要意义。

相关文章:

LeetCode 912:排序数组 | 排序算法全面解析

LeetCode 912:排序数组 | 排序算法全面解析 引言 排序数组(Sort an Array)是 LeetCode 第 912 题,难度为 Medium。题目要求将给定数组排序并返回。虽然这是一个看似简单的问题,但题目对时间和空间复杂度有要求&#xf…...

YooAsset资源治理:Unity热更新与AB包依赖管理实战

1. 为什么Unity老手一提资源管理就皱眉:从AssetBundle的“三座大山”说起在Unity项目做到中后期,几乎每个主程都会经历这么一个深夜:打包时间突然从3分钟涨到12分钟;热更包体积比预期大出40%,CDN带宽告急;策…...

随机森林与Busy函数在天文光谱分类中的实战应用

1. 项目概述:当随机森林遇见宇宙光谱在射电天文学的前沿,我们每天都在与来自宇宙深处的海量数据打交道。其中,中性氢原子在21厘米波长处产生的吸收线,就像宇宙气体的“指纹”,是探测星系中冷气体分布、运动状态以及星系…...

序数回归实战:从KNN阈值优化到神经网络模型全解析

1. 项目概述:当回归遇上“有序”世界在机器学习的工具箱里,回归和分类是两大基石。回归预测连续值,比如房价、温度;分类预测离散标签,比如猫、狗、汽车。但现实世界并非总是非黑即白,有一种特殊的数据类型常…...

Java AI 应用开发实践:基于 Spring Boot 实现 Chat、Memory、RAG 与 Tool Calling

前言 这两年 AI 应用开发非常火,越来越多开发者开始尝试把大模型能力接入到自己的业务系统中,比如智能客服、知识库问答、企业助手、代码助手、数据分析助手等。 不过在实际开发过程中,我发现一个比较明显的问题: 很多 AI 应用框架…...

Unity局域网画面同步方案:FMETP STREAM低延迟多终端投射实战

1. 这不是“又一个网络同步教程”,而是解决真实产线卡点的局域网画面投射方案我第一次在客户现场看到这个需求时,是在一家做工业AR巡检系统的公司。他们刚部署完一批HoloLens 2和iPad,准备给产线工人做实时设备状态叠加显示——但问题来了&am…...

【AI搜索引擎未来5年趋势白皮书】:20位顶尖AI架构师联合预测的7大不可逆变革

更多请点击: https://intelliparadigm.com 第一章:AI搜索引擎未来5年趋势总览 AI搜索引擎正从关键词匹配的“检索工具”加速演进为具备推理能力、上下文感知与主动服务意识的“智能认知中枢”。未来五年,其技术演进将围绕多模态理解、实时知…...

Cowrie SSH蜜罐:协议层行为建模与威胁情报流水线

1. 为什么一个SSH蜜罐能比防火墙更早告诉你“有人在敲门” 你有没有过这种经历:某天凌晨三点,安全告警平台突然弹出一条“SSH暴力破解尝试激增”,点开一看——IP来自巴西、乌克兰、越南,每秒27次登录请求,用户名穷举了…...

Java NIO.2 异步基石:AsynchronousChannel 接口契约与并发安全深度剖析

前言:异步 I/O 的“宪法级”契约 在 Java NIO.2(AIO)的宏大架构中,AsynchronousChannel 是所有异步通道的根接口。它不定义任何具体的读写方法,也不关心网络拓扑或文件偏移——它只做一件事:确立异步 I/O 操…...

Unity资源归档:构建可信交付的四大技术支柱

1. 为什么“资源归档”不是打包,而是Unity项目生命周期的隐形分水岭在Unity项目做到中后期,你大概率会遇到这样几个信号:Build时间从3分钟涨到12分钟;AssetBundle生成脚本每次都要手动删旧包、清缓存、重设Variant;美术…...

JMeter WebSocket接口测试实战:从握手失败到万级压测

1. 为什么 WebSocket 测试不能只靠“点点点”——从一个线上告警说起上周五下午四点十七分,监控平台突然弹出三条红色告警:用户实时消息延迟超 3 秒、在线状态同步失败率陡升至 12%、某核心业务频道连接断开率在 5 分钟内从 0.03% 拉到 1.8%。运维同事第…...

C# 文件的输入与输出

C# 文件的输入与输出 在C#编程语言中,文件的输入与输出操作是基础且重要的技能。无论是进行数据的持久化存储,还是从文件中读取数据以供程序使用,文件操作都是程序设计中不可或缺的一环。本文将详细讲解在C#中进行文件输入与输出的方法和技巧…...

Unity入门:从创建立方体理解组件化三维工作流

1. 这不是“Hello World”,而是你和Unity第一次真正握手很多人点开Unity安装包那一刻,以为接下来就是拖拽、点击、三分钟出效果——结果新建项目后面对空荡荡的Scene视图和一堆灰色面板,连“立方体在哪”都找不到。我带过三十多期Unity新手训…...

AngularJS 控制器详解

AngularJS 控制器详解 引言 AngularJS 是一个用于构建动态网页的框架,它允许开发者使用 HTML 作为模板语言,通过指令扩展 HTML 的功能。在 AngularJS 中,控制器是核心组件之一,它负责管理视图和模型之间的交互。本文将详细介绍 AngularJS 控制器的概念、作用、创建方法以…...

Unity新手第一课:从创建立方体理解场景驱动开发

1. 这不是“Hello World”,而是你和Unity第一次真正握手很多人点开Unity,新建一个空项目,盯着灰蒙蒙的Scene视图发呆——光标悬停在空白画布上,不知道该点哪里,更不知道点下去会发生什么。我带过几十个零基础学员&…...

DeFecT-FF:机器学习力场加速半导体缺陷高通量筛选与建模

1. 项目概述:当机器学习力场遇上缺陷物理在薄膜太阳能电池,尤其是CdSeTe这类II-VI族半导体材料的研究中,有一个核心问题长期困扰着材料科学家和器件工程师:缺陷。这些原子尺度上的“不完美”——比如一个缺失的镉原子(…...

俯视角射击手感优化:从弹道计算到神经同步的完整实现

1. 这不是“加个子弹特效”那么简单:为什么俯视角射击效果必须从底层逻辑重写你打开 Unity,拖一个 SpriteRenderer 进来,挂上 Animator,再写个Instantiate(bulletPrefab)——恭喜,你做出了“能发射子弹”的游戏。但当你…...

融合链上数据与市场情绪的以太坊Gas价格预测模型实践

1. 项目概述:当链上数据遇见市场情绪在以太坊生态里混迹多年的开发者或交易员,大概都经历过这样的深夜:盯着钱包里一笔迟迟无法确认的交易,看着Gas价格像过山车一样飙升,心里盘算着是咬牙追加Gas费,还是取消…...

7net-Omni:多任务学习驱动的通用机器学习原子间势模型解析与应用

1. 项目概述:为什么我们需要一个“全能”的原子模拟模型? 在材料科学和计算化学领域,我们一直面临着一个核心矛盾:量子力学计算(如密度泛函理论,DFT)虽然精度高,但计算成本极其昂贵&…...

FinML-Chain:融合链上链下数据,构建可信金融机器学习数据集

1. 项目概述:当区块链数据遇见机器学习 在金融科技这个日新月异的领域,我们每天都在和数据打交道。无论是高频交易、风险评估还是市场预测,机器学习模型早已成为我们手中不可或缺的“利器”。但干这行久了,你一定会遇到一个绕不开…...

2026-05-24 GitHub 热点项目精选

/* 全局样式 */* { margin: 0; padding: 0; box-sizing: border-box; }body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;max-width: 900px; margin: 0 auto; padding: 30px 20px; line-height: 1.7; color: #2d3748;backgro…...

深度学习结合CT图像预测岩石渗透率:从孔隙网络到升尺度计算

1. 项目概述:当深度学习遇见岩石CT图像 在油气勘探、地热开发乃至二氧化碳地质封存这些领域,我们这些从业者最头疼的问题之一,就是如何准确知道一块岩石的“透水能力”,也就是渗透率。传统上,我们依赖实验室岩心驱替实…...

Unity源码级优化:IL织入、Native桥接与内存重排实战

1. 这不是“性能调优指南”,而是一份引擎级手术记录Unity项目优化,市面上90%的教程止步于“Profiler看CPU/GPU帧耗→查DrawCall→合批→减Shader复杂度→压贴图”。我干了八年Unity底层支持,给二十多个中大型项目做过深度介入,发现…...

Unity UI性能崩坏真相:UGUI重建机制与FGUI数据驱动协同

1. 这不是“UI怎么做”,而是“为什么UI总在上线前崩掉”我带过七支Unity项目团队,从百人MMO到独立游戏Demo,几乎每支队伍都经历过同一个深夜:美术交了新皮肤,策划改了按钮文案,程序顺手调了个CanvasScaler的…...

Unity UI性能优化实战:UGUI Canvas重建与FGUI渲染控制深度解析

1. 这不是UI框架对比,而是我在三个项目里用烂UGUI、摸透FGUI后写下的血泪清单“Unity UI开发”这六个字,听上去平平无奇,可只要你在实际项目里做过超过两个版本的界面迭代,就会发现:它根本不是拖几个Image和Text出来排…...

可观测性最佳实践:构建全面的系统监控体系

可观测性最佳实践:构建全面的系统监控体系 一、可观测性最佳实践概述 1.1 可观测性的定义 可观测性是指通过外部输出(指标、日志、追踪)来推断系统内部状态的能力。它帮助运维人员理解系统行为,快速定位问题,优化系统性…...

DMA优化与MIMO系统性能分析:6G通信关键技术

1. DMA优化与MIMO系统性能分析概述动态超表面天线(Dynamic Metasurface Antenna, DMA)作为6G通信系统的关键技术突破,正在重新定义大规模MIMO系统的设计范式。与传统的相控阵天线相比,DMA通过可编程的超表面单元实现对电磁波的精确…...

Keil MDK Middleware TCP发送性能问题分析与优化

1. 问题现象与背景分析最近在将Keil MDK Middleware从6.x版本升级到7.0.0后,发现目标设备上TCP数据包发送性能显著下降。具体表现为:当应用程序尝试以较高频率发送TCP数据包时,网络核心线程处理发送请求的速度明显变慢,导致整体吞…...

机器学习势能面构建实战:从量子化学数据到高精度分子模拟

1. 项目概述:当机器学习“学会”了化学反应的势能面在计算化学的世界里,我们一直面临着一个核心矛盾:精度与效率的权衡。如果你想精确地描述一个化学反应,比如DNA复制过程中碱基对的质子转移,你需要动用量子化学方法&a…...

深度学习解码星际湍流:从光谱图估计MHD模式能量分数

1. 项目概述与核心价值在星际介质(ISM)的研究中,磁流体动力学(MHD)湍流扮演着能量传输、物质混合和结构形成的“发动机”角色。它并非一团混沌,而是可以分解为三种具有不同物理特性的基本模式:阿…...