正整数的因子与质因子

问题

给定一个正整数,求其所有因子与质因子。所给正整数不超过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;
}
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值