使用质因数之和替换后可以取到的最小值

135 阅读1分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第 29 天,点击查看活动详情

问题描述

给你一个正整数  n 。

请你将  n  的值替换为  n  的  质因数  之和,重复这一过程。

  • 注意,如果  n  能够被某个质因数多次整除,则在求和时,应当包含这个质因数同样次数。

返回 **n **可以取到的最小值。

示例 1:

输入: n = 15
输出: 5
解释: 最开始,n = 1515 = 3 * 5 ,所以 n 替换为 3 + 5 = 88 = 2 * 2 * 2 ,所以 n 替换为 2 + 2 + 2 = 66 = 2 * 3 ,所以 n 替换为 2 + 3 = 5 。
5 是 n 可以取到的最小值。

示例 2:

输入: n = 3
输出: 3
解释: 最开始,n = 3 。
3 是 n 可以取到的最小值。

提示:

  • 2 <= n <= 10^5

思路分析

首先我们要先理解一下题目意思,题目会给我们一个整数n,我们需要将n分解成n的质因数之和,如:

n=8时,我们可以将其分解成2 * 4,同时4又可以分解成2 * 2,所以最终8应该被分解成2 * 2 * 2,n的质因数之和即为2 + 2 + 2 = 6,这时6仍可以继续分解成2 * 3,得到2 + 3 = 55无法继续分解,所以我们可以得到最终的结果为5

题目要求的是返回 n 可以取到的最小值,所以遇到一个数的质因数等于本身时,此时得到的结果即为最小值,可以直接返回该结果,具体步骤如下:

  • 1、获取质数列表

最小的质数是 2,且每个合数都可以分解成多个质数之和,所以我们可以从 2 开始,对质数的倍数进行标记,最后剩下的即为质数,如下我们使用primeNums数组保存得到的质数列表,nums记录每个数字是否为质数。

let nums = new Array(100005).fill(true);
const primeNums = [];
for (let i = 2; i < nums.length; i++) {
  if (nums[i]) {
    primeNums.push(i);
    for (let j = 2; j * i < nums.length; j++) {
      nums[i * j] = false;
    }
  }
}
  • 2、递归求质数和

前面我们已经获取到了质数的列表,现在我们只需要遍历列表,判断当前数字是否可以被质数整除,可以的话继续对其进行递归分解,直到分解出的数字都为质数即可结束递归。

const getSum = (n, sum = 0) => {
  if (nums[n]) return sum + n;
  for (const i of primeNums) {
    if (n % i == 0) {
      return getSum(n / i, sum + i);
    }
  }
};
  • 3、循环进行分解

因为我们要得到 n 可以取到的最小值,所以我们在分解之后还需继续对分解得到的数字继续进行分解,直到得到最小值(无法继续分解,或者质因数等于本身)。

while (1) {
  let nn = getSum(n);
  if (nn == n) break;
  n = nn;
}

AC 代码

完整代码如下:

/**
 * @param {number} n
 * @return {number}
 */
var smallestValue = function (n) {
  let nums = new Array(100005).fill(true);
  const primeNums = [];
  for (let i = 2; i < nums.length; i++) {
    if (nums[i]) {
      primeNums.push(i);
      for (let j = 2; j * i < nums.length; j++) {
        nums[i * j] = false;
      }
    }
  }
  const getSum = (n, sum = 0) => {
    if (nums[n]) return sum + n;
    for (const i of primeNums) {
      if (n % i == 0) {
        return getSum(n / i, sum + i);
      }
    }
  };
  while (1) {
    let nn = getSum(n);
    if (nn == n) break;
    n = nn;
  }
  return n;
};

说在后面

本人为算法业余爱好者,平时只是随着兴趣偶尔刷刷题,如果上面分享有错误的地方,欢迎指出,感激不尽。