题目
给定一个 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; } }