每日一题——使用质因数之和替换后可以取到的最小值

80 阅读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 <= 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;
    }
}