Java质数因数倍数

Posted by tianhaoo on April 28, 2021 本文阅读量

判断质数

如果n不是质数,那么在根号n之前一定有一个因数,所以只需要遍历到根号n即可

public boolean isPrime(int n){
    if(n<=1) return false;
    if(n<=3) return true;

    double upperBound = Math.sqrt(n) + 1;
    for (int i=2; i<upperBound; i++){
        if(n%i == 0) return false;
    }
    return true;

}

质数还有一个特点,就是它总是等于 6x-1 或者 6x+1,其中 x 是大于等于1的自然数。利用这个特性可以进一步优化。

求所有因数

从1到n遍历,能被整除就是因数

    public static List<Integer> allFactors(int n){
        List<Integer> res = new ArrayList<>();
        for(int i=1; i<=n; i++){
            if(n%i == 0){
                res.add(i);
            }
        }

        return res;
    }

最大公因数

直接遍历所有因数,暴力解,可行,但时间复杂度太高。

一般用如下两种解法

辗转相除法

两个正整数a和b(a>b),它们的最大公约数等于a除以b的余数c和b之间的最大公约数。

    public static int getNum(int a, int b){
        int numberA = Math.max(a, b);
        int numberB = Math.min(a, b);
        return gcd(numberA, numberB);
    }

    // a是大的,b是小的
    public static int gcd(int a, int b){
        if(a % b == 0){
            return b;
        }else{
            return gcd(b, a%b);
        }
    }

当两个整数较大时,取模运算的性能较低

更相减损术

两个正整数a和b(a>b),它们的最大公约数等于a-b的差值c和较小数b的最大公约数。

    public static int getNum2(int a, int b){
        return gcd2(a, b);
    }

    public static int gcd2(int a, int b){
        if(a==b) return a;
        int numberA = Math.max(a, b);
        int numberB = Math.min(a, b);
        return gcd2(numberA-numberB, numberB);
    }

虽然单次减法运算比取模运算快很多,但是运算次数大大增加。

两者结合起来,能够在数字比较大时获得更好的性能。

代码略

最小公倍数

利用公式

m * n / 最大公因数 = 最小公倍数

可以用辗转相除法求最大公因数