抽空看了然叔的直播打造cli工具,和造的轮子发现还有很多东西等着我去学习。"刻意学习"本身不是一件很难的事,提高认知才是学习的目的。
正题
面试题 17.09. 第 k 个数
有些数的素因子只有 3,5,7,请设计一个算法找出第 k 个数。注意,不是必须有这些素因子,而是必须不包含其他的素因子。例如,前几个数按顺序应该是 1,3,5,7,9,15,21。
示例 1:
输入: k = 5
输出: 9
解析:
这题是什么意思呢?通俗的解释就是将 3,5,7相乘(可重复使用)得到的数按照从小到大递增排序后找到第K个数是多少。用公式表达则是 3*a * 5*b * 7*c, 且a,b,c只能等于1,3,5,7
肉眼可见的最小 1,1*3,1*5,1*7,3*3,3*5,3*7就是题目所给的提示前几位:1,3,5,7,9,15,21。
那么在下一位应该是什么? 你能够知道是 5*5,这是凭借我们多年以来的数学经验知道,下一个最小的就是5 * 5 ,可通过逻辑如何确定?如果数字更大了就看不出来了,又要怎么确定?更难判定的是类似3*3*3这样3个数相乘且有很小怎么判定?其实25之后就是3*3*3 = 27了,你用直觉未必就能看出来了吧。
可否试想一下:
1.每一个数相乘后会得到一个新的值,那么这个新的值再去相乘就可以覆盖 三个数相乘的结果了
2.标记每次相乘的结果,当时用过这个数之后,这个数就和第二小的数相乘,以此类推
也许你听不明白,本来我也说不明白。。那么下面一张图,教你如何利用动态规划来找第K个素因子:
(能用图就绝不打字)是否可以稍微明白了呢?
再结合代码去深入思考一下,就一定好理解了:
/**
* @param {number} k
* @return {number}
*/
var getKthMagicNumber = function(k) {
let dpList = new Array(k + 1).fill(1)
let p3 = 0
let p5 = 0
let p7 = 0
for (let index = 1 ; index <= k ; index++) {
const number3 = dpList[p3] * 3
const number5 = dpList[p5] * 5
const number7 = dpList[p7] * 7
console.log({number3, number5, number7})
const min = Math.min(number3, number5, number7)
min === number3 && p3++
min === number5 && p5++
min === number7 && p7++
dpList[index] = min
}
return dpList[k - 1]
};