题目链接
思路分析
题目中又一次提到了有序,就能够猜想能够使用二分法
- 那么如果要使用二分的话,我们就需要左右边界,我们寻找的是某一个元素,因此我们考虑使用数组的值域,在数组中,左上和右下分别是最小和最大值,我们可以通过求解中值的方法来不断缩小范围
- 当我们得到一个中值之后,需要注意的就是如何计算比中值小的数字的数量
- 从最后一行开始统计,若当前值小于mid,由于每一列也都是升序排列,所以这一列也都小于mid,可以加入num,
- 如果这一整列都小于mid的话,对j++
- 如果当前数大于mid的话,对i–
- 最终就能得到小于mid的num数量
- 在这之后我们就要进行二分了,根据我们返回值nums >= k可知,如果他恰好相等的话,那么mid就是我们要的数,因此可选区间在于**[left , mid]**
- 如果小于的话,可选区间在于**[mid+1, right]**
代码实现
class Solution {
public:
bool check(vector<vector<int>>& matrix, int mid, int k)
{
int n = matrix.size()-1;
int i = n;
int j = 0;
int nums = 0;
while(i >= 0 && j <= n)
{
if(matrix[i][j] <= mid)
{
nums += (i+1);
j++;
}
else
i--;
}
return nums >= k;
}
int kthSmallest(vector<vector<int>>& matrix, int k) {
int n = matrix.size();
int left = matrix[0][0];
int right = matrix[n - 1][n - 1];
while (left < right) {
int mid = left + ((right - left) >> 1);
if (check(matrix, mid, k)) {
right = mid;
} else {
left = mid + 1;
}
}
return left;
}
};