Leetcode378题有序矩阵中的第k小的数

题目

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

示例

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

返回 13

题解

本题利用二分思想进行求解,要使用二分就得有有序的区间,本题将有序区间转换为矩阵中最小值到最大值这个范围,具体二分最小值到最大值的范围区间,区间初始值为矩阵最小值和最大值。目标返回值为当左边界值left等于右边界值right时所返回的边界值。因为每次划分区间都保证了第k个数在left~right之间,所以当left==right时即为目标值。具体算法流程见代码:
class Solution {
    public int kthSmallest(int[][] matrix, int k) {
        /*
            本题利用二分思想进行求解,具体二分最小值到最大值的范围区间,区间初始值为矩阵最小值和最大值
            具体算法过程如下:
            (1).初始化二分区间左右边界值left和right
            (2).重复以下步骤直到left == right:
                a.计算二分区间中位数mid
                b.二分后,统计左区间中小于mid的数字个数count
                c.如果count小于k,则继续寻找左区间,修改left值;如果大于k,则继续寻找右区间,修改right值
            (3).目标值为left,因为每次划分区间都保证了第k个数在left~right之间,所以当left==right时即为目标值
        */
        int n = matrix.length;
        int left = matrix[0][0];
        int right = matrix[n - 1][n - 1];
        while(left < right){
            int mid  = left + (right - left) / 2;
            int count = 0;
            int j = 0;
            int i = n - 1;
            while(j < n && i >= 0){    //从左下角的元素开始计算,小于等于matrix[i][j]的元素的话,则第j列的前i-1个元素一定小于等于mid,否则的话继续缩小扫描的行
                if(matrix[i][j] <= mid){
                    count += i + 1;
                    j++;
                }
                else{
                    i--;
                }
            }
            if(count < k){
                left = mid + 1;
            }
            else{
                right = mid;
            }
        }
        return left;
    }
}
原文地址:https://www.cnblogs.com/jianglinliu/p/11838936.html