利用动态规划找出3,5,7第K个素因子

531 阅读2分钟

抽空看了然叔的直播打造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个素因子:

1.gif

(能用图就绝不打字)是否可以稍微明白了呢?

再结合代码去深入思考一下,就一定好理解了:

/**
 * @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]
};