[路飞]第 K 个数

187 阅读2分钟

题目描述

有些数的素因子只有 3,5,7,请设计一个算法找出第 k 个数。注意,不是必须有这些素因子,而是必须不包含其他的素因子。例如,前几个数按顺序应该是 1,3,5,7,9,15,21。

分析

输入:k 表示要找第几个数 输出:找到的数

解题思路

题目告诉我们找到第 k 个因子只有 3,5,7 的数,那实际上就是去从小到大地去找 3,5,7 乘积的组合,我们举几个例子:

比如只有一个 3,5,7。那么是就是 3,5,7;两个 3 就是 9,3 * 5 就是 15。可以看到我们每次都需要找到一个最小的数,放在一个数据结构里,然后再找下一个数,这是要保证顺序必须是递增的,我们才能最终找到第 k 个数。

我们通过观察找规律,可以发现,在找数的过程中,每次都是前一个数字去和 3,5,7 进行乘法运算,我们只会取最小的那个,也就是用 Math.min 去拿到最小的值。

所以我们可以构建这样一个算法,通过3个指针:p3, p5, p7 来分别表示和 3,5,7 来进行相乘的那个数字所在 index,如果本轮和 3 进行了乘法运算,p3 就向前移动一位,对于 5 和 7 也是如此。

OK,主要的计算过程就是这些。还需要注意 ⚠️ 的一点是,我们在计算的过程中,可能会有重复的情况,比如 3 * 5 与 5 * 3,我们可以这样,只要本轮计算完发现 3,5,7 中的某个是本轮计算结果的因子,就直接让他对应的 index 向前走一步,这样就减少了重复~

代码

/**
 * @param {number} k
 * @return {number}
 */
var getKthMagicNumber = function (k) {
  const dp = [1]
  let p3 = 0
  let p5 = 0
  let p7 = 0

  for (let i = 1; 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 - 1]
}

getKthMagicNumber(9)

复杂度

时间:O(N),复杂度与 k 正相关
空间:O(N),存储 k 个数据