在这里插入图片描述
在这里插入图片描述

文章目录

    • 摘要
    • 描述
    • 题解答案
    • 题解代码分析
      • 代码解析
    • 示例测试及结果
      • 输出结果
    • 时间复杂度
    • 空间复杂度
    • 总结

摘要

在开发中,我们经常遇到需要处理大规模有序数据的场景,比如数据库分页、排行榜查询、或者处理排序过的矩阵。LeetCode 第 378 题“有序矩阵中第 K 小的元素”就是这样一个经典问题:它要求我们在一个行列都排好序的矩阵中,快速找到第 K 小的元素。本文将结合代码、算法思路和实际场景,带大家拆解这个题目的解法。

描述

题目要求我们在一个 n × n 的有序矩阵 中找到第 K 小的元素。矩阵的特点是:

  • 每一行是按升序排列的;
  • 每一列也是按升序排列的。

换句话说,矩阵不仅仅是二维数组,它在行和列两个维度上都保持有序。
我们需要返回排序后第 K 小的那个元素,而不是第 K 个不同的元素。

比如:

输入:matrix = [[1,5,9],[10,11,13],[12,13,15]], k = 8
输出:13
解释:矩阵展开后是 [1,5,9,10,11,12,13,13,15],第 8 小的数是 13

这个问题在实际开发中也很常见,比如:

  • 在数据库表中进行多字段排序后,查找某个偏移量的数据;
  • 在分布式日志系统中,根据时间和序号找到某条具体日志;
  • 在推荐系统里,找到用户兴趣排序中的第 K 个候选项。

题解答案

针对这个问题,有几个常见的思路:

  1. 最直接的做法:把矩阵“扁平化”,拉成一个数组,然后排序,再取第 K 个。

    • 时间复杂度:O(n² log n²),太大。
    • 空间复杂度:O(n²),内存开销也大。
  2. 利用小顶堆(最小堆):每一行都是有序的,所以我们可以把每行的第一个元素丢进最小堆,每次弹出最小值,再把该元素所在行的下一个元素压入堆。这样循环 K 次,就能得到第 K 小的元素。

    • 时间复杂度:O(k log n)。
  3. 二分查找 + 计数:利用矩阵整体有序的性质,在数值范围内进行二分搜索,统计小于等于 mid 的元素个数。根据计数结果收缩区间,直到找到第 K 小的数。

    • 时间复杂度:O(n log(max-min)),比堆解法更节省内存。

这里我们选择 二分查找的解法,因为它更高效,也符合题目“内存复杂度优于 O(n²)”的要求。

题解代码分析

下面是 Swift 的实现代码,使用二分查找:

import Foundationclass Solution {func kthSmallest(_ matrix: [[Int]], _ k: Int) -> Int {let n = matrix.countvar left = matrix[0][0]var right = matrix[n - 1][n - 1]func countLessEqual(_ mid: Int) -> Int {var count = 0var row = n - 1var col = 0// 从左下角开始统计 <= mid 的元素个数while row >= 0 && col < n {if matrix[row][col] <= mid {count += row + 1col += 1} else {row -= 1}}return count}// 二分查找while left < right {let mid = left + (right - left) / 2if countLessEqual(mid) < k {left = mid + 1} else {right = mid}}return left}
}

代码解析

  1. leftright 分别是矩阵中的最小值和最大值,作为二分查找的边界。

  2. countLessEqual(mid) 用来统计矩阵中小于等于 mid 的元素个数。这里从 左下角 开始走,效率高。

    • 如果当前元素 ≤ mid,那么这一列到当前行的所有数都 ≤ mid,所以 count += row + 1
    • 如果当前元素 > mid,就往上一行走。
  3. 在二分查找过程中,如果统计结果 < k,说明 mid 太小,需要右移;否则收缩右边界。

  4. 最终 left 就是第 K 小的数。

示例测试及结果

let solution = Solution()let matrix1 = [[1,5,9],[10,11,13],[12,13,15]]
print(solution.kthSmallest(matrix1, 8))  
// 输出: 13let matrix2 = [[-5]]
print(solution.kthSmallest(matrix2, 1))  
// 输出: -5

输出结果

13
-5

这和题目示例完全一致,说明算法是正确的。

时间复杂度

二分查找在区间 [min, max] 上进行,区间大小是数值范围,复杂度是 O(log(max-min))
每次统计时,需要遍历一行或一列,总共 O(n)。
因此总体复杂度是:
O(n log(max-min))

对于 n = 300 的规模,这个复杂度是可以接受的。

空间复杂度

整个算法只使用了几个变量,没有额外的存储结构,空间复杂度是:
O(1)

相比直接展开矩阵存储,节省了大量内存,非常适合大规模数据。

总结

这道题考察的关键点在于 如何利用矩阵的有序性

  • 如果直接暴力排序,肯定超时或内存爆炸。
  • 用堆可以解决,但还是会有 O(n) 的额外存储。
  • 最优解是二分查找 + 计数,既利用了矩阵的有序性,又避免了额外存储。

在实际业务中,这个思路同样适用:

  • 处理数据库分页查询时,可以用“数值二分 + 索引统计”来代替大规模排序。
  • 在大规模日志或指标矩阵中查找排名时,也可以用这个思路快速定位。

所以,这道题不仅是算法练习,更是一种 高效思维方式 的锻炼。

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

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

相关文章

【Lua】Windows 下编写 C 扩展模块:VS 编译与 Lua 调用全流程

▒ 目录 ▒&#x1f6eb; 导读需求环境1️⃣ 核心原理&#xff1a;Windows下Lua与C的交互逻辑2️⃣ Windows下编写步骤&#xff1a;以mymath模块为例2.1 步骤1&#xff1a;准备Windows开发环境方式1&#xff1a;官网下载Lua源码并编译&#xff08;可控性高&#xff09;方式2&am…

Python快速入门专业版(二十九):函数返回值:多返回值、None与函数嵌套调用

目录引一、多返回值&#xff1a;一次返回多个结果的优雅方式1. 多返回值的本质&#xff1a;隐式封装为元组示例1&#xff1a;返回多个值的函数及接收方式2. 多返回值的接收技巧技巧1&#xff1a;用下划线_忽略不需要的返回值技巧2&#xff1a;用*接收剩余值&#xff08;Python …

python使用pip安装的包与卸载

1&#xff1a;基本卸载命令 # 卸载单个包 pip uninstall package_name# 示例&#xff1a;卸载requests包 pip uninstall requests2&#xff1a;卸载多个包 # 一次性卸载多个包 pip uninstall package1 package2 package3# 示例 pip uninstall requests numpy pandas3&#xff1…

超级流水线和标量流水线的原理

一、什么是流水线&#xff1f;要理解这两个概念&#xff0c;首先要明白流水线&#xff08;Pipelining&#xff09; 的基本思想。想象一个汽车装配工厂&#xff1a;* 没有流水线&#xff1a;一个工人负责组装一整辆汽车&#xff0c;装完一辆再装下一辆。效率很低。* 有了流水线&…

【Ansible】管理复杂的Play和Playbook知识点

1.什么是主机模式&#xff1f;答&#xff1a;主机模式是Ansible中用于从Inventory中筛选目标主机的规则&#xff0c;通过灵活的模式定义可精准定位需要执行任务的主机。2.主机模式的作用答&#xff1a;筛选目标&#xff1a;从主机清单中选择一个或多个主机/组&#xff0c;作为P…

FastGPT源码解析 Agent 智能体应用创建流程和代码分析

FastGPT对话智能体创建流程和代码分析 平台作为agent平台&#xff0c;平台所有功能都是围绕Agent创建和使用为核心的。平台整合各种基础能力&#xff0c;如大模型、知识库、工作流、插件等模块&#xff0c;通过可视化&#xff0c;在界面上创建智能体&#xff0c;使用全部基础能…

缺失数据处理全指南:方法、案例与最佳实践

如何处理缺失数据&#xff1a;方法、案例与最佳实践 1. 引言 在数据分析和机器学习中&#xff0c;缺失数据是一个普遍存在的问题。如何处理缺失值&#xff0c;往往直接影响到后续分析和建模的效果。处理不当&#xff0c;不仅会浪费数据&#xff0c;还可能导致模型预测结果的不准…

为什么Cesium不使用vue或者react,而是 保留 Knockout

1. Knockout-ES5 插件的语法简化优势 自动深度监听&#xff1a;Cesium 通过集成 Knockout-ES5 插件&#xff0c;允许开发者直接使用普通变量语法&#xff08;如 viewModel.property newValue&#xff09;替代繁琐的 observable() 包装&#xff0c;无需手动声明每个可观察属性。…

Word怎么设置页码总页数不包含封面和目录页

有时候使用页码格式是[第x页/共x页]或[x/x]时会遇到word总页数和实际想要的页数不一致&#xff0c;导致显示不统一&#xff0c;这里介绍一个简单的办法&#xff0c;适用于比较简单的情况。 一、wps版本 文章分节 首先将目录页与正文页进行分节&#xff1a;在目录页后面选择插入…

突破机器人通讯架构瓶颈,CAN/FD、高速485、EtherCAT,哪种总线才是最优解?

引言&#xff1a; 从协作机械臂到人形机器人&#xff0c;一文拆解主流总线技术选型困局 在机器人技术飞速发展的今天&#xff0c;从工厂流水线上的协作机械臂到科技展会上的人形机器人&#xff0c;它们的“神经系统”——通讯总线&#xff0c;正面临着前所未有的挑战。特斯拉O…

Java核心概念详解:JVM、JRE、JDK、Java SE、Java EE (Jakarta EE)

1. Java是什么&#xff1f; Java首先是一种编程语言。它拥有特定的语法、关键字和结构&#xff0c;开发者可以用它来编写指令&#xff0c;让计算机执行任务。核心特点&#xff1a; Java最著名的特点是“一次编写&#xff0c;到处运行”&#xff08;Write Once, Run Anywhere - …

OSPF高级技术 相关知识点

1.多区域OSPFospf 设计多区域原因&#xff1a;① 每个区域的路由器只需同步自己所在区域的链路状态数据库&#xff0c;分区域设 计可以使得每个区域的链路状态数据库得以减少。以降低路由器cpu、内存 的消耗。② 避免某区域内的网络故障&#xff08;例如&#xff1a;接口频繁up…

Linux / Windows 下连续发送多帧 8 字节指令,下位机只响应第一帧,第二帧“丢失”。

串口编程易错点笔记 基于 serial::Serial&#xff08;wjwwood serial 库&#xff09; 场景&#xff1a;Linux / Windows 下连续发送多帧 8 字节指令&#xff0c;下位机只响应第一帧&#xff0c;第二帧“丢失”。1. 现象 serial::Serial ser("/dev/ttyUSB0", 115200);…

三十九、案例-配置文件-参数配置化(了解即可,现在主流使用yml配置文件)

参数配置化-问题引出参数配置化-问题解决参数配置化-代码与过程解析代码&#xff1a; AliOSSUtils&#xff08;工具类&#xff09; package com.itheima.utils;import com.aliyun.oss.OSS; import com.aliyun.oss.OSSClientBuilder; import org.springframework.beans.factory.…

Linux之virtio实现原理--pci 基础

一、概述 virtio设备可以基于不同总线来实现&#xff0c;本文介绍基于pci实现的virtio-pci设备。以virtio-blk为例&#xff0c;首先介绍PCI配置空间内容&#xff0c;virtio-pci实现的硬件基础——capability&#xff0c;最后分析PIC设备的初始化以及virtio-pci设备的初始化。 …

Claude-Flow AI协同开发:从“CTO”到“人机共生体”的AI协同开发

6.1 思维的终极融合&#xff1a;从“CTO”到“人机共生体” (Human-AI Symbiote) 在之前的章节中&#xff0c;我们逐步将您的角色从“开发者”提升为“项目经理”&#xff0c;最终定位为整个“人机混合团队的CTO”。这个模型强调的是一种 “指挥-控制” (Command-and-Control) …

TCGA单癌肿按单基因高低分组的转录组差异热图分析作图教程

TCGA单癌肿按单基因高低分组的转录组差异热图分析作图教程分析作图原理过程提取出TCGA中指定的单基因单癌肿的转录组表达数据对该单基因的表达水平的中位数作为阈值把样本分成高表达组和低表达组按该基因的高低表达样本分组来做该癌症的转录组差异分析对差异分析结果中top差异高…

手搓Tomcat

目录 Tomcat是什么&#xff1f; 前置工作准备 构建并启动Tomcat 处理Socket逻辑顺序 获取输入流并读取数据封装到Request 自定义Servlet对象 暂存响应体 按Http协议发送响应数据 部署Tomcat ​ Tomcat是什么&#xff1f; Tomcat 是一个 Web 应用服务器&#xff08;准确…

Linux网络:初识网络

文章目录1. 网络发展1.1 独立模式1.2 网络互联1.3 局域网LAN1.4 广域网WAN2. 认识 “协议”2.1 什么是协议&#xff1f;2.2 为什么要有协议&#xff1f;2.3 深入了解协议序&#xff1a;开网络之篇章&#xff0c;建网络之基础&#xff0c;将近2月过去&#xff0c;暑假期间不曾有…

文件检查与拷贝-简化版

本篇继续来学习shell脚本&#xff0c;对上一篇的文件检查与拷贝脚本进行简化修改。 1 功能说明 在Linux系统中&#xff0c;通过一个shell脚本&#xff0c;实现将一个目录中的所有文件&#xff08;包括子目录中的&#xff09;&#xff0c;拷贝到顶一个指定的目录&#xff0c;要求…