378. Kth Smallest Element in a Sorted Matrix
在一个矩阵中找到第k小的元素,矩阵可包含重复值,每行,每列递增。
利用二分法主要是要找到区间,并不断缩小。区间又主要来自两个地方:序列号和元素值,大部分都是依据数组的序列号,也有小部分是通过元素值,本体就是。
- l设为矩阵最小值,r为最大值
- 每次取其中值m,计算矩阵中小于m的元素的个数count
- 如果count小于k,说明m最多是第count小的,而第k小的元素肯定比m大,往m值后面找
- 否则,第k小的元素肯定小于等于m,往前面继续找
public int kthSmallest(int[][] matrix, int k) {
int l = matrix[0][0], r = matrix[matrix.length-1][matrix[0].length-1] + 1;
while (l < r) {
int m = l + (r - l) / 2;
int count = 0, j = matrix[0].length-1;
//计算小于m的个数count
for (int i = 0; i < matrix.length; i++) {
while (j >=0 && matrix[i][j] > m)
j--;
count += j+1;
}
//如果count小于k,说明m最多是第count小的,而第k小的元素肯定比m大,往m值后面找
//否则,第k小的元素肯定小于等于m,往前面继续找
if (count < k)
l = m + 1;
else
r = m;
}
return l;
}
668. Kth Smallest Number in Multiplication Table
和上题几乎一样,只是矩阵换成了一个乘法表,找第k小的元素。
- 首先乘法表是固定的,给出了m,n,k。我们就可以比较这几个值的大小来缩小查找范围,比如m > k,那么大于k的部分就没有看的必要了,因为大于k的所有行肯定全都大于k
- 剩下的解题结构和上题也几乎一样,只不过每次循环算大于m的元素个数的计算方式发生了变化
public int findKthNumber(int m, int n, int k) {
//缩小范围
int i = Math.min(m, k);
int j = Math.min(n, k);
int l = 1, r = i * j;
while (l < r) {
int mid = l + (r - l) / 2;
int count = 0;
for (int o1 = 1; o1 <= i; o1++) {
//计算每行小于mid的元素个数
int o2 = Math.min(mid/o1, j);
count += o2;
}
if (count < k)
l = mid + 1;
else
r = mid;
}
return l;
}