leetcode 378. Kth Smallest Element in a Sorted Matrix(排好序的矩阵中第K小的元素)

这篇博客介绍了如何在每行每列都排好序的矩阵中,使用二分搜索算法寻找第k小的元素。由于矩阵特性,普通的二分搜索需要调整策略,通过从左下角开始,逐列向上计数来确定小于目标值的元素数量。这种方法具有O(logn)的时间复杂度和O(1)的空间复杂度。博客提供了详细的算法实现和示例解释。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Given an n x n matrix where each of the rows and columns is sorted in ascending order, return the kth smallest element in the matrix.

Note that it is the kth smallest element in the sorted order, not the kth distinct element.

You must find a solution with a memory complexity better than O(n2).

Example 1:

Input: matrix = [[1,5,9],[10,11,13],[12,13,15]], k = 8
Output: 13
Explanation: The elements in the matrix are [1,5,9,10,11,12,13,13,15], and the 8th smallest number is 13
Example 2:

Input: matrix = [[-5]], k = 1
Output: -5

矩阵的每行每列都是排好序的,返回第k小的元素。
注意每行的元素并不是全都比下一行的元素小。

思路:

Binary Search

如果保证每行都比下一行的元素小,那就比较好办,直接binary search就行。
现在的难点在于每行不一定都比下一行元素小,只是保证了每行和每列是排好序的,
比如例子1中第2行有13,而第3行有比它小的12。

所以这里的binary search要换个思路,找到比mid 值小的元素有多少个,
如果比k个少,说明这个mid值应该大一些,需要提高左边界,
同样的,如果比k个多,说明mid应该小一些,需要降低右边界。

直到左右边界重合,则找到了第k小的元素。

那么怎么找比mid值小的有多少个呢,
可以一行一行逐个元素地比较,记下个数。

也有一个比较巧的方法,就是从左下角的元素开始,一列一列地看,
举个例子,
1, 5, 9
10, 11, 13
12, 13, 15
假如mid = 12, 首先看第1列(到左下角的元素12),
12 <= mid, 而列又是排好序的,所以整个一列的3个元素都记入,count += 3
下一列,13>mid, 所以往上一行,11 < mid, 那么11上面的列也要记入, count += 2,
再往右,到13,13>mid, 往上一行,9 < mid, 记入count += 1,
再下一列,超出边界,终止。
这个是从左下角到右上角的遍历方法。

当然也可以逐行逐元素遍历。

public int kthSmallest(int[][] matrix, int k) {
    int n = matrix.length;
    int low = matrix[0][0];
    int high = matrix[n-1][n-1];
    
    while(low < high) {
        int mid = low + (high - low) / 2;
        int count = lessThan(matrix, mid);
        
        if(count < k) {
            low = mid + 1;
        } else {
            high = mid;
        }
        
    }
    return low;
}

int lessThan(int[][] matrix, int target) {
    int n = matrix.length;
    int i = n - 1;
    int j = 0;
    int count = 0;
    
    while(i >= 0 && j < n) {
        if(matrix[i][j] > target) {
            i --;
        } else {
            count += (i + 1);
            j ++;
        }
    }
    return count;
}

参考链接

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

蓝羽飞鸟

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值