求两个不全为零的非负整数最大公约数

下面的代码中一共有三种实现方法,分别是分别使用欧几里得算法、连续整数检测算法、公因数算法

1、欧几里得算法:

两个值不停的去相除,直到他们相除的余数为零时,得到结果,公约数为此时的被除数。

我实现的方法是递归的方法,非递归应该也行,等哪辈子我再试试。

2、连续整数检测算法:

从两个数中较小的那个开始,不停的去检测,是否是输入的两个数的约数,如果是就返回结果,不是就将检测值减一继续进行检测。

因为是从大到小的顺序进行检测,所以只要是约数,就必定是最大的那个。

3、公因数算法:

这个算法相对前两个实现起来麻烦了许多。

将输入的两个值分解为几个质数的乘积的形式,然后去检测他们的这几个质数是否有相同的,取出相同的,其乘积就是结果。

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

public class Work1 {

    public Work1(){

        for ( int i = 0; i < 10; i++ ){

            int a = (int)(Math.random() * 1000);
            int b = (int)(Math.random() * 1000);

            System.out.println( "a:" + a + " b:" +b + " \t");
            System.out.print( gcd1( a, b ) + " \t");
            System.out.print( gcd2( a, b ) + " \t" );
            System.out.println( gcd3( a, b ) );
        }
    }

    //欧几里得算法,递归
    public int gcd1( int m, int n ){

        //对输入有0的特殊情况进行处理
        if ( Math.min(m, n) == 0 ){
            return Math.max(m,n);
        }

        //其实只有在第一次的时候使用判断,进入递归之后永远都是m>n
        if ( m > n ){

            //当m/n的余数为零的时候结束递归,返回结果n
            //余数不为零就进行下一次递归
            if ( m%n == 0 )
                return n;
            else
                return gcd1( n, m%n );
        }else {
            if ( n%m == 0 )
                return m;
            else
                return gcd1( m, n%m );
        }

    }

    //连续整数检测算法
    public int gcd2( int a, int b ){

        //t为a、b中的较小值
        int t = Math.min( a, b );

        //当t不为零时
        while ( t > 0 ){

            //当t符合条件时返回结果,否则将t减一
            if ( a%t == 0 && b%t == 0 ){
                return t;
            }else
                t--;
        }

        //只有在t为零的时候会到这里,返回另一个不为零的值
        return t==0 ? Math.max(a, b ) : t;
    }

    //公因数算法
    public int gcd3( int m, int n ){

        //对t为零的时候进行处理
        if ( Math.min(m, n) == 0 ){
            return Math.max(m,n);
        }

        //调用方法,得到两个数的分解结果
        List<Integer> list1 = allPrime(m);
        List<Integer> list2 = allPrime(n);

        int result = 1;

        //调整两个list的顺序,使list1为较短的那个list
        if ( list1.size() > list2.size() ){
            List tmp = list1;
            list1 = list2;
            list2 = tmp;
        }

        //依次遍历list1,从list2中查询是否含有当前位置的值
        for ( int i = 0; i < list1.size(); i++ ){

            //判断list2中是否含有当前位置的值
            //如果含有这个值,使其与result相乘,并将其移出list2
            if ( list2.contains(list1.get(i)) ){
                list2.remove(list1.get(i) );
                result *= list1.get(i);
            }
        }

        return result;
    }

    //将n分解为几个质数,这几个质数的乘积为n
    public List allPrime( int n ){

        List<Integer> output = new ArrayList<Integer>();        //存储结果
        List<Integer> list = new ArrayList<Integer>();

        //output.add(1);

        //对几种特殊情况进行处理
        if ( n > 2 ){
            list.add(2);
        }else if ( n ==1 ){
            return output;
        }else{
            output.add(2);
            return output;
        }

        //求n以内的所有因数
        boolean isPrime = true;
        for ( int i = 3; i <= n; i++ ){
            isPrime = true;

            //判断i是否为质数
            for ( int j = 2; j <= i/2 +1; j++ ){
                if ( i%j == 0 ){
                    isPrime = false;
                    break;
                }
            }

            //若是将i添加在list中
            if ( isPrime ){
                list.add(i);
            }
        }

        //开始进行因式分解
        //当n为质数的时候,无法分解,直接返回结果
        if ( list.get( list.size()-1 ) == n ){
            output.add(n);
        }else {

            int num = n;
            while ( num != 1 ){

                //依次遍历整个n以内的质数,直到结束
                for ( int i = 0; i < list.size(); i++ ){
                    if ( num%list.get(i) == 0 ){
                        num = num/list.get(i);
                        output.add(list.get(i));
                        break;
                    }
                }
            }
        }

        return output;
    }

    public static void main(String[] args) {
        Work1 work1 = new Work1();
    }
}
发布了48 篇原创文章 · 获赞 1 · 访问量 840

猜你喜欢

转载自blog.csdn.net/weixin_45980031/article/details/104329596