一日一练:丑数II

106 阅读2分钟

给你一个整数 n ,请你找出并返回第 n 个 丑数 。丑数 就是只包含质因数 23 和/或 5 的正整数

三指针

因为只包含质因数235,所以结果肯定是这些因数的乘积。这里比较难的是怎们可以让乘积可以从小到大依次被计算。这里使用三指针, 分别指向235下次相乘的数值 所在结果数组中的位置。

  1. 初始化结果数组为[1],开始都是与1相乘,即都从索引0开始,所以三指针数组初始化为[0, 0, 0]
  2. 235相乘之后得到乘积为235,其中2为最小值,将其推入结果中[1, 2],修改2对应的指针,指针数组为[1, 0, 0]
  3. 继续相乘:235与索引相对应值相乘之后得到乘积为4353为最小值推入结果数组[1, 2, 3]3的指针+1,即[1, 1, 0]
  4. 继续相乘结果为465,其中4为最小值,加入结果[1, 2, 3, 4],同时修改2的指针,得到指针[2, 1, 0]
  5. 继续相乘结果为665,其中5为最小值,加入结果[1, 2, 3, 4, 5],同时修改5的指针,得到指针[2, 1, 1]
  6. 继续相乘结果为6610,其中6为最小值,加入结果[1, 2, 3, 4, 5, 6],同时修改23的指针,得到[3, 2, 1]
  7. 以此类推...

代码:

function nthUglyNumber(n: number): number {
  const res: number[] = [1]
  const rates = [0, 0, 0]
  const set = new Set([1])
  while(res.length !== n) {
      let r2 = res[rates[0]] * 2
      let r3 = res[rates[1]] * 3
      let r5 = res[rates[2]] * 5
      let min = Math.min(r2, r3, r5)
      res.push(min)
      if (min === r2) {
          rates[0]++
      }
      if (min === r3) {
          rates[1]++
      }
      if (min === r5) {
          rates[2]++
      }
  }
  return res[res.length - 1]
};