求两个数的最大公约数的3种办法

import org.junit.Test;

import java.util.ArrayList;
import java.util.List;

/**
 * 求两个数的最大公约数
 * @author shadowolf
 * @date 2018/10/24 12:25
 */
public class GreatestCommonDivisor {

    @Test
    public void greatestCommonDivisor() throws Exception {
        int result1 = GreatestCommonDivisor.getGreatestComonDivisor1(24, 60);
        System.out.println("result1: " + result1);
        int result2 = GreatestCommonDivisor.getGreatestComonDivisor2(24, 60);
        System.out.println("result2: " + result2);
        int result3 = GreatestCommonDivisor.getGreatestComonDivisor3(24, 60);
        System.out.println("result3: " + result3);
    }

    /**
     * 欧几里得算法
     */
    public static int getGreatestComonDivisor1(int num1, int num2) throws Exception {
        if (num1 < 1 || num2 < 1) {
            throw new Exception("params error !");
        }
        if (num1 < num2) {
            int temp = num1; num1 = num2; num2 = temp;
        }
        int r = num1 % num2;
        while (r != 0) {
            num1 = num2;
            num2 = r;
            r = num1 % num2;
        }
        return num2;
    }

    /**
     * 连续整数检测算法
     */
    public static int getGreatestComonDivisor2(int num1, int num2) throws Exception {
        if (num1 < 1 || num2 < 1) {
            throw new Exception("params error !");
        }
        if (num1 < num2) {
            int temp = num1; num1 = num2; num2 = temp;
        }
        if (num1 % num2 == 0) {
            return num2;
        }
        int t = num2 - 1;
        while (num1 % t != 0 || num2 % t != 0) {
            t--;
        }
        return t;
    }

    /**
     * 质因数算法
     */
    public static int getGreatestComonDivisor3(int num1, int num2) throws Exception {
        if (num1 < 1 || num2 < 1) {
            throw new Exception("params error !");
        }
        if (num1 < num2) {
            int temp = num1; num1 = num2; num2 = temp;
        }
        // 求出2-n的所有质数序列
        List<Integer> primeNumList = getToNPrimeNumber(num1);
        List<Integer> num1PrimeList = getNAllPrimeNumber(num1, primeNumList);
        List<Integer> num2PrimeList = getNAllPrimeNumber(num2, primeNumList);
        List<Integer> commonList = getTwoLCommonList(num1PrimeList, num2PrimeList);
        int result = 1;
        for (Integer l : commonList) {
            result *= l;
        }
        return result;
    }

    /**
     * 求2-n中的质数序列
     * 使用算法: 埃拉托色尼筛选法
     */
    public static List<Integer> getToNPrimeNumber(int n) {
        List<Integer> primeNumList = new ArrayList<>();
        int[] nums = new int[n+1];
        for (int p = 2; p <= n; p++) {
            nums[p] = p;
        }
        for (int p = 2; p < Math.floor(Math.sqrt(n)); p++) {
            int nn = p * p;
            while (nn <= n) {
                nums[nn] = 0;
                nn += p;
            }
        }
        for (int p = 2; p <= n; p++) {
            if (nums[p] != 0) {
                primeNumList.add(nums[p]);
            }
        }
        return primeNumList;
    }

    /**
     * 求n的所有质因数序列
     */
    public static List<Integer> getNAllPrimeNumber(Integer num, List<Integer> primeNumList) {
        List<Integer> numPrimeList = new ArrayList<>();
        int i = 0;
        while (i < primeNumList.size() && num != 1) {
            if (num %  primeNumList.get(i) == 0) {
                numPrimeList.add(primeNumList.get(i));
                num /= primeNumList.get(i);
                i = 0;
                continue;
            }
            i++;
        }
        return numPrimeList;
    }

    /**
     * 求两个序列的共有序列
     */
    public static List<Integer> getTwoLCommonList(List<Integer> list1, List<Integer> list2) {
        List<Integer> commonList = new ArrayList<>();
        for (Integer l : list1) {
            if (list2.contains(l)) {
                commonList.add(l);
            }
        }
        return commonList;
    }

}

转载于:https://my.oschina.net/shadowolf/blog/2252066

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值