有序矩阵中第K小的元素

给你一个 n x n矩阵 matrix ,其中每行和每列元素均按升序排序,找到矩阵中第 k 小的元素。

请注意,它是 排序后 的第 k 小元素,而不是第 k不同 的元素。

你必须找到一个内存复杂度优于 O(n2) 的解决方案。

示例 1:

复制代码
输入:matrix = [[1,5,9],[10,11,13],[12,13,15]], k = 8
输出:13
解释:矩阵中的元素为 [1,5,9,10,11,12,13,13,15],第 8 小元素是 13

示例 2:

复制代码
输入:matrix = [[-5]], k = 1
输出:-5

思路

由题目给出的性质可知,这个矩阵内的元素是从左上到右下递增的。

我们知道整个二维数组中 matrix00 为最小值,matrixn−1n−1 为最大值,现在我们将其分别记作 l 和 r。

可以发现一个性质:任取一个数 mid 满足 l≤mid≤r,那么矩阵中不大于 mid 的数,肯定全部分布在矩阵的左上角。

例如下图,取 mid=8:

我们可以看到,矩阵中大于 mid 的数就和不大于 mid 的数分别形成了两个板块,沿着一条锯齿线将这个矩形分开。其中左上角板块的大小即为矩阵中不大于 mid 的数的数量。

可以这样描述走法:

初始位置在 matrixn−10(即左下角);

设当前位置为 matrixij。若 matrixij≤mid,则将当前所在列的不大于 mid 的数的数量(即 i+1)累加到答案中,并向右移动,否则向上移动;

不断移动直到走出格子为止。

简单说一下关于 "为什么left一定在矩阵中" 的理解 ?

  1. 循环过程中,矩阵中第k小的那个数始终在区间left, right

  2. 循环过程中,left和right可能不是矩阵中的元素,但是left, right中某个元素 "在矩阵中" 且 "满足第k小"

  3. 当right == left时,right, left中只有一个元素了(即left),所以此时left必然 "在矩阵中" 且 "满足第k小"

还有一个陷阱,和搜索旋转排序数组 类似,必须写成 right=mid,left=mid+1,而不能

right=mid-1,left=mid,因为后者在只有两个数的时候可能会跳不出循环。

python 复制代码
from typing import List


class Solution:
    def kthSmallest(self, matrix: List[List[int]], k: int) -> int:
        n=len(matrix)

        def check(mid:int)->bool:
            i,j=n-1,0
            num=0
            while i>=0 and j<n:
                if matrix[i][j]<=mid:
                    num+=(i+1)
                    j+=1
                else:
                    i-=1
            return num>=k


        left, right =matrix[0][0], matrix[-1][-1]
        while left<right:
            mid = (left + right) // 2
            if check(mid):
                right = mid
            else:
                left = mid + 1
        return left

自己的写法:

python 复制代码
import heapq
from typing import List


class Solution:
    def kthSmallest(self, matrix: List[List[int]], k: int) -> int:
        n=len(matrix)
        shuzu=[]
        for i in range(n):
            shuzu.append((matrix[0][i],i))
        heapq.heapify(shuzu)
        while k:
            cur=heapq.heappop(shuzu)
            x,y=cur[1]//n,cur[1]%n
            if x+1<n:
                heapq.heappush(shuzu,(matrix[x+1][y],cur[1]+n))
            k-=1

        return cur[0]
相关推荐
Jerry21 小时前
LeetCode 56. 合并区间
算法
天天有money1 天前
API中转站在社媒矩阵里的价值:多平台文案如何统一改写
gpt·线性代数·ai·chatgpt·矩阵
实验如有神祝女士1 天前
不同参数规模大模型在医学翻译场景的适配差异
论文阅读·人工智能·深度学习·学习·算法·语言模型·论文笔记
windliang1 天前
Claude Code 源码分析(三):一次模型回答如何流进 Agent
前端·算法·ai编程
Kyrie_kk1 天前
Java--BigInteger 超大整数计算
java·算法
神明不懂浪漫1 天前
【第三章】链表
开发语言·数据结构·经验分享·笔记·链表
汽车网络安全爱好者1 天前
Public Key Infrastructure(二)— 深入理解 X.509 证书:从 RFC 5280 到 OpenSSL 实践
运维·服务器·算法·网络安全·汽车·密码学·可信计算技术
tkevinjd1 天前
力扣131-分割回文串
算法·leetcode·深度优先
BioRunYiXue1 天前
技术干货 | LiP-MS全流程解析:从实验设计到数据分析
大数据·前端·javascript·人工智能·算法·数据挖掘·数据分析
Jasmine_llq1 天前
《P11246 [GESP202409 六级] 小杨和整数拆分》
算法·数学定理版本·时间复杂度n1/2·dp 版本