开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第29天,点击查看活动详情
使用质因数之和替换后可以取到的最小值
给你一个正整数 n 。
请你将 n 的值替换为 n 的 质因数 之和,重复这一过程。
- 注意,如果
n能够被某个质因数多次整除,则在求和时,应当包含这个质因数同样次数。
返回 **n **可以取到的最小值。
示例 1:
输入: n = 15
输出: 5
解释: 最开始,n = 15 。
15 = 3 * 5 ,所以 n 替换为 3 + 5 = 8 。
8 = 2 * 2 * 2 ,所以 n 替换为 2 + 2 + 2 = 6 。
6 = 2 * 3 ,所以 n 替换为 2 + 3 = 5 。
5 是 n 可以取到的最小值。
示例 2:
输入: n = 3
输出: 3
解释: 最开始,n = 3 。
3 是 n 可以取到的最小值。
提示:
2 <= n <= 105
思路
题目非常好理解,宏观上的思路也很清晰,我们需要找到 n 的质因数,然后将其相加组成一个新的值赋予 n,直到找不到 n 的质因数为止。
首先我们要做的,就是找到质数,但并不是所有的质数我们都需要,如果质数大于等于 n 则这个质数是根本不会使用的,只会占用内存空间,故我们在获取质数时,只需要找到小于 n 的质数集合即可。
对于 n 来说,如果可以被质数整除,则可以直接操作,因为 n 的质因数一定是唯一的,不会出现其他的情况。
对于循环的终止情况,有两种,一种是 n 已经是质数了,此时 n 不可能被其他质数整除,故可以返回结果;另一种情况是前一状态的 n 和 n 的质因数相加得到的新的 n相等,此时如果继续操作则会无限循环,故需要我们判断这种情况来终止循环。
题解
class Solution {
public int smallestValue(int n) {
List<Integer> list = new ArrayList<>();
for(int i = 2; i <= n; i++) {
if(isPrime(i)) {
list.add(i);
}
}
int tmp = 0;
while(!list.contains(n)) {
int before = n;
for(int i: list) {
while(n != 1 && n % i == 0) {
tmp += i;
n /= i;
}
if(n == 1) {
n = tmp;
tmp = 0;
break;
}
}
if(n == before) {
return n;
}
}
return n;
}
private boolean isPrime(int n) {
for(int i = 2; i * i <= n; i++) {
if(n % i == 0) {
return false;
}
}
return true;
}
}