问题
给定一个正整数,求其所有因子与质因子。所给正整数不超过long类型的最大表示范围。
输入样例
60
输出样例
[1, 60, 2, 30, 3, 20, 4, 15, 5, 12, 6, 10]
[2, 3, 5]
求因子
/**
*
* 理论: 首先明确几个数学概念和结论
* 1.一个数的自身和1都是其因子;
* 2.一个数的因子总是成对出现num=m*n;
* 3.如果m不等于n,则m和n必定分别位于区间[1, sqrt(num))和(sqrt(num),num]
*
* 只需要在2<=i<=sqrt(num))范围之内判断i是否是num的因子即可
*
*/
public static ArrayList<Long> getFactors(long N){
ArrayList<Long> list = new ArrayList<>();
list.add(1L);//1必是N的因子
if(1 == N)
return list;
else
list.add(N);//N大于1时,N必是自身的因子
final long SQRT_N = (long) Math.sqrt(N);
//检验2到根号SQRT_N之间的数是否是因子
for(long i = 2; i <= SQRT_N; i++){
if(0 == N % i){
long r = N / i;
list.add(i);
if(r > i)
list.add(r);
}
}
return list;
}
求质因子
/**
*
* 理论: 首先明确几个数学概念和结论
* 1.奇数必定没有偶数因子;
* 2.所有质数(除了2)都是奇数;
* 3.正整数分为质数、合数和1,任一合数必定可以写成若干个质数因子之积(可能会有重复质因子,比如12=2*2*3);
*
* 从质数2开始,寻找目标整数num的因子(能整除num就是因子),如果当前因子出现多次,
* 那么都记录下来,且每次都从num中除去该因子,从而每次得到的因子必定是质因子。
* 因为合数因子本身必定可以写成若干个质数因子之积,而我们是从最小的质数开始寻找, 所以如果能被num整除,则一定是质因子。
*
* 比如num=12,其因子有1、2、3、4、6、12,其中质因子有2和3 由于4=2*2 ,6=2*3,所以当i=4或6时,num%i != 0
*
*/
public static ArrayList<Long> primeFactors(long num) {
ArrayList<Long> list = new ArrayList<>();
// 判断质数2是不是num的因子,即num是不是偶数
boolean flag = true;
while ((num & 1) == 0) {
num >>= 1;
// 只在第一次出现该质因子时记录
if (flag) {
list.add(2L);
flag = false;
}
}
// 此时num必定已经是奇数,只需要检验奇数是不是num的质因子
// 如果i是num的因子,则必定是质因子,记录之
// 如果i不是num的因子,则在下一轮循环中检验下一个奇数i+2是不是num的因子
for (long i = 3; i <= num; i += 2) {
flag = true;
while (num % i == 0) {
num /= i;//如果i是因子,从num中去除该因子,重复出现几次就去除几次
if (flag) {
list.add(i);
flag = false;//避免list中多次记录相同的因子i
}
}
}
return list;
}