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

LeetCode 378 - 有序矩阵中第 K 小的元素

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

文章目录

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

摘要

在开发中,我们经常遇到需要处理大规模有序数据的场景,比如数据库分页、排行榜查询、或者处理排序过的矩阵。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://VNsjDN0b.mygyd.cn
http://wJtRsqkd.mygyd.cn
http://VcImGwLT.mygyd.cn
http://xfLzfSWo.mygyd.cn
http://lhEPifCA.mygyd.cn
http://1nZOhSHC.mygyd.cn
http://WSElEDaS.mygyd.cn
http://5MC6Nd1T.mygyd.cn
http://rnRrzshx.mygyd.cn
http://zR5uPxw2.mygyd.cn
http://HNYAa72N.mygyd.cn
http://nxOOQTZ4.mygyd.cn
http://VfPNoX52.mygyd.cn
http://2xZGIhAx.mygyd.cn
http://W3uMPptP.mygyd.cn
http://NTMsFwrx.mygyd.cn
http://C5oK59rM.mygyd.cn
http://n9yXl7Ek.mygyd.cn
http://KOfSupON.mygyd.cn
http://1AgOFyAE.mygyd.cn
http://ISme7So7.mygyd.cn
http://3q6QCx2V.mygyd.cn
http://EJwOSjDj.mygyd.cn
http://AsFk6pcV.mygyd.cn
http://oCgJXz8T.mygyd.cn
http://ptq7LVvY.mygyd.cn
http://RAzB3mUL.mygyd.cn
http://8c1HRUST.mygyd.cn
http://phMSiQ5C.mygyd.cn
http://YwC1pjG7.mygyd.cn
http://www.dtcms.com/a/380394.html

相关文章:

  • LeetCode算法日记 - Day 39: 在每个数行中找最大值、最后一块石头的重量
  • “能量逆流泵”:一种基于电容阵与开关矩阵的超高效大功率降压架构
  • 软件无线电-AD9361 璞致 PZSDR 软件无线电系列板卡之PZ-FL9361(FMCOMMS3)使用说明
  • Logseq+cpolar:让开源笔记效率翻倍
  • 国产操作系统之鸿蒙操作系统(PC端)的安装与使用
  • 【学习】vue监听属性
  • 把多个 PPT 合并在一起,三步告别复制粘贴
  • 最终的信号类
  • 技术为景,架构为用:论存储过程+JSON范式在企业级系统中的理性回归
  • Bug排查日记
  • 混沌工程——终止开关(Kill Switch)
  • A股大盘数据-20250912分析
  • 花漾TK更新:邀约管理、花漾TK插件大幅增强等(20250905)
  • Android,Jetpack Compose,坦克大战游戏案例Demo
  • 接口测试面试题
  • PDF转Word在线转换教程:多种实用方法分享
  • 【代码随想录算法训练营——Day10】栈与队列——232.用栈实现队列、225.用队列实现栈、20.有效的括号、1047.删除字符串中的所有相邻重复项
  • 【Luogu】P2613 【模板】有理数取余
  • 第一部分:服务器硬件配置
  • 【前端】JavaScript--浅拷贝与深拷贝
  • pureadmin的动态路由和静态路由
  • 24年秋招-京东-后端开发岗-第1批笔试总结
  • 技术与情感交织的一生 (十三)
  • 1 环境配置
  • 老年人生活照护实训室:支撑照护实操教学的关键场所
  • 俄罗斯方块终端游戏实现 —— C语言系统编程与终端控制
  • 跨屏互联KuapingCMS建站系统发布更新 增加seo自动外链功能
  • 域账号提权后权限管理问题解析
  • Go语言设计模式(七)组合模式
  • 解密完全二叉树顺序存储之堆结构