试除法分解质因数
 试除法分解质因数 
 初始版本
1
2
3
4
5
6
7
8
9
10
11
12
public List<Integer> getPrimeList(int num) {
    List<Integer> factors = new ArrayList<>();
    // 0,1不为质数,从2开始遍历
    for (int i = 2; i * i <= num; i++) {         // 优化点:只遍历到 sqrt(num)
        if (num % i == 0) {                      // 能整除,i 为 num 的因数
            factors.add(i);
            while (num % i == 0) num /= i;
        }
    }
    if (num > 1) factors.add(num);
    return factors;
}
从最小质数 2 开始遍历,并将 i 除尽,保证较大的合数被较小的质数分解。
例如:遍历到 4 时,此时 num 已没有因数 2,所以 num % 4 != 0 会跳过。
加一次列表,再试除,保证质因数列表不重复。
优化版本
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public List<Integer> getPrimeList(int num) {
    List<Integer> factors = new ArrayList<>();
    if (num < 2) return factors;
    // 特殊处理
    if (num % 2 == 0) {
        factors.add(2);
        while (num % 2 == 0) num /= 2;
    }
    // 步长为2,只遍历奇数
    for (int i = 3; i * i <= num; i += 2) {
        if (num % i == 0) {
            factors.add(i);
            while (num % i == 0) num /= i;
        }
    }
    if (num > 1) factors.add(num);
    return factors;
}
所有质数中只有 2 为偶数,先处理掉 2,接下来只遍历奇数。
预处理版本
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public List<Integer> getPrimeList(int num) {
    List<Integer> factors = new ArrayList<>();
    for (int prime = 2; prime < isPrime.length; prime++) {
        if (!isPrime[prime]) continue;
        if (prime * prime > num) break;
        if (num % prime == 0) {
            factors.add(prime);
            while (num % prime == 0) num /= prime;
        }
    }
    
    if (num > 1) factors.add(num);
    return factors;
}
通过质数筛预处理,可以看这篇博客:质数筛。
假设已预处理得到一个 isPrime 数组,只需要遍历质数,判断是否为因数即可。
要点:isPrime 数组长度需要大于 num 开根。
 本文由作者按照  CC BY 4.0  进行授权