持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第17天,点击查看活动详情
编程世界总是离不了算法
最近在看框架源码时,会有很多算法的实现逻辑,有时候会感到吃力
于是决定蹭着假期,加强算法和数据结构相关的知识
那怎么提升呢?
其实我知道算法这东西没有捷径,多写多练才能提升,于是我开启我的LeetCode
刷题之旅
第一阶段目标是:200
道,每天1
到2
篇
为了不乱,本系列文章目录分为三部分:
- 今日题目:xxx
- 我的思路
- 代码实现
今日题目:668. 乘法表中第k小的数
几乎每一个人都用 乘法表。但是你能在乘法表中快速找到第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] 之间。
来源:力扣(LeetCode) 链接:leetcode.cn/problems/kt… 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
我的思路
假设给的的乘法表是 33 的,我们要找第 5小的数,如果乘法表中小于等于 3 的数字有 5 个,那么3是在这个乘法表中一定是第5小的。当然3也可以是第4小的,即在33的乘法表中 3 最大是第 5 小的,还可以再小。 记乘法表中小于 mid 的数字有 smallerCount 个。
- smallerCount < k ,mid 最大情况不足 第k小,因此 将mid及小于mid的数在区间中剔除,left = mid+1
- smallerCount >= k,mid 最大情况 比k大,但是!!但是乘法表中可能有很多个 mid,所有mid需要保,比mid大的数字在区间中剔除,right = mid
代码实现
/**
* @param {number} m
* @param {number} n
* @param {number} k
* @return {number}
*/
var findKthNumber = function (m, n, k) {
let left = 1, right = m * n;
while (left < right) {
const mid = left + ((right - left) >> 1);
console.log(left, right, mid)
if (smallerCount(m, n, mid) >= k) {
// 细节:二分查找过程中取得的值不一定在乘法表中,所有在 smallerCount = k的时候不能直接retun mid;
right = mid;
} else {
left = mid + 1;
}
}
// 此时有 left === right,区间缩为一个点,即为答案
return left;
};
// 辅助函数
/**
* 统计乘法表中有多个数字小于等于 num
* @param {number} m - 乘法表的高度
* @param {number} n - 乘法表的宽度
* @param {number} num
* @param {number} count - m*n乘法表中小于等于 num 的数字数量,即在m*n的乘法表中 num 最多是第 count 小的
*/
const smallerCount = function (m, n, num) {
let count = 0;
// 统计第i行小于 num 的数目
for (let i = 1; i <= m; i++) {
count += Math.min(Math.floor(num / i), n);
}
return count;
}
总结
实现方式其实有很多,这里仅供参考~
由于刚开始刷题,也不知道从哪里刷好,如果前辈们有好的建议,希望不吝赐教,感谢🌹