几乎每一个人都用 乘法表。但是你能在乘法表中快速找到第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=9*10^8,不可取。
二分思想,二分枚举第k小的数mid, mid的值初始一定在[1, m*n]之间。统计乘法表中小于等于mid的元素个数,这里如果还是简单遍历的话,复杂度O(m*n),需要一种快速的方法。
从第一行i=1开始遍历,这一行满足小于等于mid的元素有min(mid/1, n)个,类似的,第二行满足条件的元素有min(mid/2, n),...第i行有min(mid/i, n),遍历到min(mid, m)行即可,后面的满足条件的元素均为0,不用考虑。
class Solution {
public:
int findKthNumber(int m, int n, int k) {
int low = 1, high = m*n, mid, cnt;
while (low<high) //循环结束low=high指向第k小的元素
{
mid = low + (high-low)/2;
cnt = 0;
for (int i=1; i<=min(m, mid); ++i)
cnt += min(mid/i, n);
if (cnt<k)
low = mid + 1; //low指向结果所在区间左边界
else
high = mid; //high指向有边界
}
return high;
}
};
这里需要格外注意二分循环条件和边界的更新。
注意:
m 和 n 的范围在 [1, 30000] 之间。
k 的范围在 [1, m * n] 之间。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/kth-smallest-number-in-multiplication-table
版权声明:本文为weixin_38730718原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。