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

给定一个 n x n 矩阵,其中每行和每列元素均按升序排序,找到矩阵中第k小的元素。
请注意,它是排序后的第k小元素,而不是第k个元素。

示例:

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

返回 13。

思路:

  • 二分查找, 并计算每一次小于等于中间值的元素个数
  • 如果<k, 前半段舍掉, 否则后半段舍掉
  • 计算小于等于m的个数时, 分别对每一行再次二分查找
  • class Solution {
        public int kthSmallest(int[][] matrix, int k) {
            int r = matrix.length;
            int c = matrix[0].length;
            int l = matrix[0][0];
            int h = matrix[r-1][c-1];
            while(l < h)
            {
                int m = (l+h)/2;
                int count = findNumber(matrix, m);//计算matrix里小于等于m的数. 为什么不能只是小于?因为底下一行已经没有把m考虑在内了,直接跳过m, l = m+1, 所以现在必须把m考虑进来
                if(count < k) l = m+1;
                else h = m;
            }
            return l;
        }
    
        public int findNumber(int[][] matrix, int a)
        {
            int r = matrix.length;
            int c = matrix[0].length;
            int count = 0;
            for(int i = 0; i< r; i++)
                {
                    int l = 0;
                    int h = c;
                    while(l < h)
                    {
                        int m = (l+h)/2;
                        if(matrix[i][m]<= a)l = m+1;//为什么必须小于等于?
                        else h = m;
                    }
                    count += l;
                }
            return count;
        }
    }

    这里有个细节问题, 我纠结了一会后来才想通:

  • 为什么必须要计算小于等于m的元素个数, 不能只是小于m的元素个数? 

  • 因为底下一行已经没有把m考虑在内了,直接跳过m, l = m+1, 所以现在必须把等于m的个数考虑进来.

  • 所以相应的,也可以有另外一种写法, 底下一行再考虑等于m的情况.

  • class Solution {
        public int kthSmallest(int[][] matrix, int k) {
            int r = matrix.length;
            int c = matrix[0].length;
            int l = matrix[0][0];
            int h = matrix[r-1][c-1];
            while(l < h)
            {
                int m = (l+h+1)/2;
                int count = findNumber(matrix, m);
                if(count < k) l = m;
                else h = m+1;
            }
            return l;
        }
    
        public int findNumber(int[][] matrix, int a)
        {
            int r = matrix.length;
            int c = matrix[0].length;
            int count = 0;
            for(int i = 0; i< r; i++)
                {
                    int l = 0;
                    int h = c;
                    while(l < h)
                    {
                        int m = (l+h)/2;
                        if(matrix[i][m]< a)l = m+1;
                        else h = m;
                    }
                    count += l;
                }
            return count;
        }
    }

     

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值