这是我参与2022首次更文挑战的第21天,活动详情查看:2022首次更文挑战
有些数的素因子只有 3,5,7,请设计一个算法找出第 k 个数。注意,不是必须有这些素因子,而是必须不包含其他的素因子。例如,前几个数按顺序应该是 1,3,5,7,9,15,21。
示例 1:
输入: k = 5
输出: 9
注意,不是必须有这些素因子,而是必须不包含其他的素因子。例如,前几个数按顺序应该是 1,3,5,7,9,15,21。
隐藏提示1
明确这个问题的要求。要求满足 3a× 5b× 7c 这一形式的第 k 小的值。
隐藏提示2
蛮力解法得到的形如 3a× 5b × 7c 的第 k 小的值是什么样的?
隐藏提示3
在寻找 3a × 5b × 7c 的第 k 个最小值时,我们知道 a、b、c 将小于等于 k。你能生成所有可能的数字吗?
隐藏提示4
查看 3a×5b×7c 对应的所有值的列表,可以观察到列表中的每个值都是 3×(列表中前面的某值)、5×(列表中前面的某值)或 7×(列表中前面的某值)。
隐藏提示5
由于每个数字都是列表中先前值的 3 倍、5 倍或 7 倍,因此我们可以检查所有可能的值,然后选择下一个还没有看到的值。这将导致许多重复的工作。如何才能避免这种情况呢?
隐藏提示6
不要检查列表中的所有值来寻找下一个值(通过将每个值乘以 3、5、7),而是这样考虑:当你将一个值 x 插入列表时,可以“构造”3x、5x 和 7x 以供以后使用。
隐藏提示7
当你将 x 添加到前 k 个值的列表中时,可以将 3x、5x 和 7x 添加到新的列表中。如何使其尽可能地优化?保留多个队列如何?总是需要插入 3x、5x 和 7x 吗? 或者,有时你只需要插入 7x?你需要避免相同的数字出现两次。
看完这个写提示看感觉这个题是人说的话嘛?根本不是,经过大量数据的测试发现算的是他们幂运算
当i = 0; idx1 = idx2 = idx3 = 0 时,3的0次幂 X 5的0次幂 * 7的0次幂 = 1
当i = 1; idx1 = 1, idx2 = idx3 = 0 时, 值为 3
当i = 2; idx1 = 0, idx2 = 1, idx3 = 0 时, 值为 5
当i = 3; idx1 = 0, idx2 = 0, idx3 = 1 时, 值为 7
当i = 4; idx1 = 2, idx2 = 0, idx3 = 0 时, 值为 9
当i = 5; idx1 = 1, idx2 = 1, idx3 = 0 时, 值为 15
当i = 6; idx1 = 1, idx2 = 0, idx3 = 1 时, 值为 21
这不相当于 [1,3,9,27, ...], [1,5,25,125, ...], [1,7,49,345, ...] 三个数列的排列组合嘛
我们把每个数组都定义一个下标,然后从每个数组的第一元素开始乘,然后按照从小到大的顺序排列,我们会发现 3 x 5 和 5 x 3 是一样的,我们就需要去重了,也就是当前的值如果存在数组中,我们就把对应的下标加一,跳过就行了
/**
* @param {number} k
* @return {number}
*/
var getKthMagicNumber = function(k) {
var idx1 = 0;
var idx2 = 0;
var idx3 = 0;
var stash = new Array(k)
stash[0] = 1
for(let i = 1; i < k; i++){
stash[i] = Math.min(stash[idx1] * 3, stash[idx2] * 5, stash[idx3] * 7)
// 去重
if(stash[i] == stash[idx1] * 3) idx1 ++;
if(stash[i] == stash[idx2] * 5) idx2 ++;
if(stash[i] == stash[idx3] * 7) idx3 ++;
}
return stash[k - 1]
};