【矩阵二分】力扣378. 有序矩阵中第 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

二分

csharp 复制代码
class Solution {
public:
    bool check(vector<vector<int>>& matrix, int mid, int k, int n){
        int i = n - 1;
        int j = 0;
        int num = 0;
        while(i >= 0 && j < n){
            if(matrix[i][j] <= mid){
                num += i + 1;
                j++;
            }
            else{
                i--;
            }
        }
        return k <= num;
    }


    int kthSmallest(vector<vector<int>>& matrix, int k) {
        int n = matrix.size();
        int left = matrix[0][0];
        int right = matrix[n-1][n-1];
        while(left < right){
            int mid = (left + right) >> 1;
            if(check(matrix, mid, k, n)){
                right = mid;
            }
            else{
                left = mid + 1;
            }
        }
        return left;
    }
};

时间复杂度:O(nlog(r−l)) ,二分查找进行次数为 O(log(r−l)),每次操作时间复杂度为 O(n)。
空间复杂度:O(1)

矩阵中最小的元素是matrix00,最大的元素是matrixn-1n-1,这道题使用二分查找的思想就是我们从最小数到最大数之间任意挑一个数字作为mid。假设mid = 8,根据图片,矩阵可以分成两个部分,一个部分全部小于等于8,另外一个部分全部大于8。我们可以统计左上部分小于等于8的数的数量,看8在排序后是第几小的数(因为图片有多个8,所以返回的是8是第几小的数的最大情况,即升序排列中最右边的8的位置)。

所以在二分查找中,我们从取left + right除以2的值为mid,如果在check函数中得出来左上部分的数量大于等于我们所期待的k,那么就说明我们的取的mid大于等于实际元素,这时候我们就将right = mid,缩小他的上界。如果左上部分数量小于我们所期待的k,说明我们取的mid比实际元素要小,我们令left = mid + 1,增加他的下界。

很多人会疑问left怎么确保一定是矩阵中的数?

如题解中所说,如果 num >= k,那么说明最终答案 x <= mid;如果 num < k,那么说明最终答案 x > mid。 在最后一次迭代时,check返回的结果为false,即 num < k,说明 x > mid,又因为 x <= right。当 left = mid + 1 后,left >= righ,while循环结束。此时有 mid < x <= right <= left = mid + 1,即 mid < x <= mid + 1。可得 x = mid + 1 = left。

相关推荐
土司大王4 小时前
LeetCode hot100——两两交换链表中的节点
算法·leetcode·职场和发展
zander2585 小时前
LeetCode 300. 最长递增子序列
算法·leetcode·深度优先
欧叶冲冲冲5 小时前
Python常见数据结构的CRUD(LeetCode高频版速查)
数据结构·python·leetcode
圣保罗的大教堂6 小时前
leetcode 3622. 判断整除性 简单
leetcode
Lyyaoo.7 小时前
【普通数组】【中等】除了自身以外数组的乘积
数据结构·算法·leetcode
ACP广源盛139246256737 小时前
Qwen3.8‑2.4T 开源落地@ACP#国产 Serdes 长距离视频传输芯片 GSV5800 在私有化 AI 服务中的价值与应用场景
大数据·数据库·人工智能·嵌入式硬件·矩阵·开源·音视频
圣保罗的大教堂8 小时前
leetcode 2996. 大于等于顺序前缀和的最小缺失整数 简单
leetcode
圣保罗的大教堂8 小时前
leetcode 3702. 按位异或非零的最长子序列 中等
leetcode
青 春 记 忆10 小时前
LeetCode 206. 反转链表|Python 解法详解
python·leetcode·链表