「这是我参与11月更文挑战的第21天,活动详情查看:2021最后一次更文挑战」
有些数的素因子只有 3,5,7,请设计一个算法找出第 k 个数。注意,不是必须有这些素因子,而是必须不包含其他的素因子。例如,前几个数按顺序应该是 1,3,5,7,9,15,21。
示例 1:
输入: k = 5
输出: 9
动态规划+指针+小根堆
这道题用到了动态规划,指针和小根堆的思想,我们要找出所有只包含3,5,7素因子的数,而且需要从小到大排列,所以我们需要算出,每一步的最小值,因为只包含3,5,7所以后面的数必定都从这三个数中得来,也必定是与这三个数多次相乘的结果,所以我们在计算下一个数时,则需要从前面的数中,找到合适的数与这三个数相乘,来得到下一个最小的数,这便用到了动态规划的思想,同时我们需要三个指针分别指向3,5,7,用之前计算所得的数乘以他们从而得到新的最小值,当此时2,5,7与当前值计算过之后则需要将该指针指向下一个数字,这样避免重复计算,再将三个数计算的结果进行比较取最小值。
- 生成一个长度为K+1,元素都为1的数组,
- 从下标为2开始,填充计算所得数
- 将p3,p5,p7都指向下下标为1的数,与之相乘找到乘积最小的指针
- 记录最小的指针数到数组中,并将该指针+1
- 判断其余指针有没有乘积相同的情况,如果有,指针+1
其实就是从下标为2时,开始填充,从下标为1时开始计算,三个指针都指向下标为1的数,也就是1,取出最小值,为3,即dp[p3]3=1,此时dp[2]=3,而31已经计算过了,所以p3++,代表,下次计算时,3不和1相乘,和下一个最小数3相乘作比较。
var getKthMagicNumber = function (k) {
let dp = new Array(k + 1).fill(1)
let p3 = 1, p5 = 1, p7 = 1;
for (let i = 2; i <= k; i++) {
dp[i] = Math.min(dp[p3] * 3, dp[p5] * 5, dp[p7] * 7)
if (dp[i] == dp[p3] * 3) p3++
if (dp[i] == dp[p5] * 5) p5++
if (dp[i] == dp[p7] * 7) p7++
}
return dp[k]
};