几乎每一个人都用 乘法表。但是你能在乘法表中快速找到第k
小的数字吗?
给定高度m
、宽度n
的一张 m * n
的乘法表,以及正整数k
,你需要返回表中第k
小的数字。
例 1:
输入: m = 3, n = 3, k = 5 输出: 3 解释: 乘法表: 1 2 3 2 4 6 3 6 9 第5小的数字是 3 (1, 2, 2, 3, 3).
例 2:
输入: m = 2, n = 3, k = 6 输出: 6 解释: 乘法表: 1 2 3 2 4 6 第6小的数字是 6 (1, 2, 2, 3, 4, 6).
注意:
m
和n
的范围在 [1, 30000] 之间。k
的范围在 [1, m * n] 之间。
方法一:二分查找
题目可以转换为,求有多少个数不超过 x。对于每一行 i,所有数都是 i 的倍数,不超过 x 的个数有 x / i
个。
二分枚举 x,累加每一行不超过 x 的个数,得到 cnt。找到 cnt >= k
的最小 x。
class Solution:
def findKthNumber(self, m: int, n: int, k: int) -> int:
left, right = 1, m * n
while left < right:
mid = (left + right) >> 1
cnt = 0
for i in range(1, m + 1):
cnt += min(mid // i, n)
if cnt >= k:
right = mid
else:
left = mid + 1
return left
class Solution {
public int findKthNumber(int m, int n, int k) {
int left = 1, right = m * n;
while (left < right) {
int mid = (left + right) >>> 1;
int cnt = 0;
for (int i = 1; i <= m; ++i) {
cnt += Math.min(mid / i, n);
}
if (cnt >= k) {
right = mid;
} else {
left = mid + 1;
}
}
return left;
}
}
class Solution {
public:
int findKthNumber(int m, int n, int k) {
int left = 1, right = m * n;
while (left < right)
{
int mid = (left + right) >> 1;
int cnt = 0;
for (int i = 1; i <= m; ++i) cnt += min(mid / i, n);
if (cnt >= k) right = mid;
else left = mid + 1;
}
return left;
}
};
func findKthNumber(m int, n int, k int) int {
left, right := 1, m*n
for left < right {
mid := (left + right) >> 1
cnt := 0
for i := 1; i <= m; i++ {
cnt += min(mid/i, n)
}
if cnt >= k {
right = mid
} else {
left = mid + 1
}
}
return left
}
func min(a, b int) int {
if a < b {
return a
}
return b
}