leetcode 378——有序矩阵中第k小的数

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

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

k = 8,
返回 13。

解释:排序后的数组为{1, 5, 9, 10, 11, 12, 13, 13, 15}

解题思路:
这道题很巧妙的运用了二分查找的方法,但和普通的二分查找又有区别,考验了我们是否能够灵活的运用二分查找。

  1. 找出二维矩阵中最小的数left,最大的数right,那么第k小的数必定在left~right之间
  2. mid = (left + right) / 2;在二维矩阵中寻找小于等于mid的元素个数count
  3. 若这个count小于k,表明第k小的数在右半部分且不包含mid,即区间[mid+1, right]内,又保证了第k小的数在left~right之间
  4. 若这个count大于k,表明第k小的数在左半部分且可能包含mid,即[left, mid],又保证了第k小的数在left~right之间
  5. 因为每次循环中都保证了第k小的数在left~right之间,当left==right时,第k小的数即被找出,等于right

注意:这里的left mid right是数值,不是索引位置。

代码实现:

class Solution {
public:
    int kthSmallest(vector<vector<int>>& matrix, int k) {
        int rows = matrix.size();
        int cols = rows;
        int left = matrix[0][0];
        int right = matrix[rows-1][cols-1];
        
        while (left < right)
        {
            int mid = left + ((right - left) >> 1);
            int n = findNotBiggerMidNumber(matrix, mid, rows, cols);    //找到矩阵中小于等于mid的元素个数
            if (n < k) {        //第k小的数一定在[mid+1, right]内
                left = mid + 1;
            }
            else {              //第k小的数一定在[left, mid]内
                right = mid;
            }
        }
        
        return right;
    }
    
private:
    //寻找矩阵中小于等于mid的元素个数
    int findNotBiggerMidNumber(const vector<vector<int>>& matrix, int mid, int rows, int cols)
    {
        int n = 0;
        int i = rows - 1;   //从左下角开始
        int j = 0;
        while (i >= 0 && j < cols)  //以列为单位进行统计
        {
            if (matrix[i][j] > mid) {
                --i;
            }
            else {      //matrix[i][j] <= mid
                ++j;
                n += (i + 1);
            }
        }
        
        return n;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值