大家好,我是怒码少年小码。
欧几里得算法
也叫辗转相除法。常常用于求两个数的最大公因数(gcd)。规则:若r是 a / b 的余数,则gcd(a,b) = gcd(b,r)
至于原理可以看这个视频教程:
还是没懂可以看这个文字介绍:
这里就直接上代码了:
cpp
int gcd(int a,int b){
int k;
do{
k=a % b;
a = b;
b = k;
}while(k !=0 )
return a;
}
素数和合数
素数又称为质数,素数首先要满足大于等于2,并且除了1和它本身之外,不能被任何自然数整除,其他数都是合数。比较特殊的是1即非素数,也非合数。2是唯一的同时为偶数和素数的数字。
如何判断一个正整数为素数
基本的方式是从2开始依次与n取余测试,看看是否出现n%i == 0的情况,如果出现则说明当前的n能被i整除,所以就不是。从2开始遍历一直到n^(1/2)即可。(思考一下为什么?)
java
public static boolean isPrime(int num) {
int max = (int)Math.sqrt(num);
for (int i = 2; i <= max; i++) {
if (num % i == 0) {
return false;
}
}
return true;
}
这个方法的性能不够,n很大时会超时。下面还有一种方式很有效。
埃式筛
如何使用埃式筛判断n之前的数字有多少个质数
基本思想:如果x是质数,那么大于x的xy的倍数 2x. 3x ...一定不是质数,可以从这一点入手。
首先,定义一个n大的数组保存有多少个质数。数组初始化全为1,表示每个位置上都是质数。
先选中数字2,2是素数,然后将2的倍数全部排除(在数组里将该位置标记为0)
接着选中数字3,3是素数,然后将3的倍数全部排除
接着选中数字5,5是素数,然后将5的倍数全部排除
接着选择7,11,13一直到n ...
最后在统计数组中1的个数就可以了。
java
public static int countPrimes2(int n) {
int[] isPrime = new int[n];
Arrays.fill(isPrime,1);
int ans = 0;
for (int i = 2; i < n ;i++){
if (isPrime[i] == 1){
ans += 1;
//开始排除倍数
if ((long) i * i < n){
for (int j = i* i ; j < n ; j += i){
isPrime[j] = 0;
}
}
}
}
return ans;
}
丑数问题
丑数:只包含质因子2、3和5的数。判断一个数是不是丑数。
思路分析:
根据丑数的定义,0和负整数一定不是丑数
当n > 0时,若 n 是丑数,则 n 可以写成 n = 2^a + 3^b + 5^c
的形式,其中a,b,c都是非负整数。比如说,当a,b,c都是0时,n = 1
为了判断n 是否满足上述形式,可以对n反复除以2,3,5,直到n 不再包含质因数2,3,5。若剩下的数等于1,则说明n不包含其他质因数,是丑数;否则,说明n包含其他质因数,不是丑数。
java
public boolean isUgly(int n){
if(n <= 0){
return false;
}
int[] factors = {2,3,5};
for(int factor: factors){
while( n % factor == 0){
n /= factor;
}
}
return n==1;
}