利用二分法解决 leetcode 378. Kth Smallest Element in a Sorted Matrix

问题简述

给定一个 n×n 的矩阵,矩阵中每行和每列的元素都按升序排列。给定一个 k(k[1,n2]) , 求再整个矩阵中按从小到大排序为 k 的元素。
例如:

matrix = [
   [ 1,  5,  9],
   [10, 11, 13],
   [12, 13, 15]
],
k = 8,

return 13.

解题思路

该矩阵的行和列都是按从小到大的顺序排列的,这样的问题一般都是可以用二分法解决的。再来看,我们的输入 k,输出是第 k 大的元素,不难发现,k 越大,输出的元素也就越大。好了,决定用二分法了~
首先,我们以整个矩阵中的最小值为下边界(左上角元素),最大值为上边界(右下角元素)。然后用二分的方法猜过去,猜输出的结果是多少。只要满足猜的条件,我们就会把整个元素记录下来,然后看看有没有比这个元素小,并且满足猜的条件的元素。这个过程的时间复杂度为 O( log(maxValminVal) ) ,其中的 minVal 为矩阵左上角的元素, maxVal 为矩阵右下角的元素。
好了,接下来就是看看怎么猜了~
这里猜的时候又用到了一次二分法,其目的是找到每行中不大于猜的值 val 的数有多少,然后算出整个矩阵中不大于 val 的数有多少。如果不大于 val 的数大于 k 则返回true,否则返回false。这个过程的时间复杂度为 O( nlog(n) )。这一步是可以进一步优化的~
这个过程的时间复杂度为 O( nlog(n)log(maxValminVal) )
最后,上代码~

代码

class Solution {
private:
    bool guess(vector<vector<int>>& matrix, int k, int val){
        for (int i = 0; i < matrix.size(); i++){
            int left = 0;
            int right = matrix[i].size() - 1;
            int ans = 0;
            while (left <= right){
                int mid = left + (right - left) / 2;
                if (matrix[i][mid] <= val){
                    left = mid + 1;
                    ans = mid + 1;
                }
                else{
                    right = mid - 1;
                }
            }
            k -= ans;
            if (k < 1)
                return true;
        }
        return false;
    }

public:
    int kthSmallest(vector<vector<int>>& matrix, int k) {
        int n = matrix.size();
        int left = matrix[0][0];
        int right = matrix[n - 1][n - 1];
        int ans;
        while (left <= right){
            int mid = left + (right - left) / 2;
            if (guess(matrix, k, mid)){
                ans = mid;
                right = mid - 1;
            }
            else{
                left = mid + 1;
            }
        }
        return ans;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

七元权

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

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

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

打赏作者

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

抵扣说明:

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

余额充值