Leetcode 题解 - 数学-整除2

素数分解

每一个数都可以分解成素数的乘积,例如 84 = 22 * 31 * 50 * 71 * 110 * 130 * 170 * …

整除

令 x = 2m0 * 3m1 * 5m2 * 7m3 * 11m4 * …

令 y = 2n0 * 3n1 * 5n2 * 7n3 * 11n4 * …

如果 x 整除 y(y mod x == 0),则对于所有 i,mi <= ni。

最大公约数最小公倍数

x 和 y 的最大公约数为:gcd(x,y) = 2min(m0,n0) * 3min(m1,n1) * 5min(m2,n2) * ...

x 和 y 的最小公倍数为:lcm(x,y) = 2max(m0,n0) * 3max(m1,n1) * 5max(m2,n2) * ...

生成素数序列

[LeetCode] Count Primes 质数的个数

先设置一个全为true的矩阵,从2开始不断遍历技术,把2所有倍数的数都标记为false 在从3开始一次类推

3的倍数都标记为flase 如此遍历

Count the number of prime numbers less than a non-negative number, n.

Example:

Input: 10
Output: 4
Explanation: There are 4 prime numbers less than 10, they are 2, 3, 5, 7.

References:

How Many Primes Are There?

Sieve of Eratosthenes

Credits:
Special thanks to @mithmatt for adding this problem and creating all test cases.

 

这道题给定一个非负数n,让我们求小于n的质数的个数,题目中给了充足的提示,解题方法就在第二个提示埃拉托斯特尼筛法Sieve of Eratosthenes中,这个算法的过程如下图所示,我们从2开始遍历到根号n,先找到第一个质数2,然后将其所有的倍数全部标记出来,然后到下一个质数3,标记其所有倍数,一次类推,直到根号n,此时数组中未被标记的数字就是质数。我们需要一个n-1长度的bool型数组来记录每个数字是否被标记,长度为n-1的原因是题目说是小于n的质数个数,并不包括n。 然后我们来实现埃拉托斯特尼筛法,难度并不是很大,代码如下所示:

先设置一个全为true的矩阵,从2开始不断遍历技术,把2所有倍数的数都标记为false 在从3开始一次类推

3的倍数都标记为flase 如此遍历

class Solution {
    public int countPrimes(int n) {
        if(n == 1)
            return 0;
        int count = 0;
        boolean[] judge = new boolean[n];
        Arrays.fill(judge, true);
        for(int i = 2; i < n; i ++){    
            if(judge[i]){
                count++;
                for(int j = 2; i * j < n; j++)
                    judge[i*j] = false;
            } 
        }
        return count;
    }
}

最大公约数

int gcd(int a, int b) {
    return b == 0 ? a : gcd(b, a % b);
}

a : gcd(b, a % b) 6,4               4, 6 % 4  4,2       2, 4 % 2  

最小公倍数为两数的乘积除以最大公约数。

int lcm(int a, int b) {
    return a * b / gcd(a, b);
}

4 * 6 / 2 =0;

 

使用位操作和减法求解最大公约数

编程之美:2.7

对于 a 和 b 的最大公约数 f(a, b),有:

  • 如果 a 和 b 均为偶数,f(a, b) = 2*f(a/2, b/2);
  • 如果 a 是偶数 b 是奇数,f(a, b) = f(a/2, b);
  • 如果 b 是偶数 a 是奇数,f(a, b) = f(a, b/2);
  • 如果 a 和 b 均为奇数,f(a, b) = f(b, a-b);

乘 2 和除 2 都可以转换为移位操作。

public int gcd(int a, int b) {
    if (a < b) {
        return gcd(b, a);
    }
    if (b == 0) {
        return a;
    }
    boolean isAEven = isEven(a), isBEven = isEven(b);
    if (isAEven && isBEven) {
        return 2 * gcd(a >> 1, b >> 1);
    } else if (isAEven && !isBEven) {
        return gcd(a >> 1, b);
    } else if (!isAEven && isBEven) {
        return gcd(a, b >> 1);
    } else {
        return gcd(b, a - b);
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值