求最大公约数


《小灰的算法之旅》学习笔记

题目:

求两个整数的最大公约数

解决方法

一 :辗转相除法(欧几里得算法)

定理:
两个正整数a和b(a>b),它们的最大公约数等于a除以b的余数c和b之间的最大公约数

步骤:
根据以上定理,不断把两个较大的整数之间的运算,简化成两个较小整数之间的运算,直到两个数可以整除,或其中一个数减小到1为止

分析:
当两个整数较大时,a%b取模运算的性能会比较差,时间复杂度可近似为O(log(max(a,b)))

举例:
在这里插入图片描述

public int rollingPhaseDivision(int a,int b){
        int max = a>b?a:b;
        int min = a>b?b:a;
        if (max%min==0)
            return min;
        return rollingPhaseDivision(max%min,min);
    }

二: 更相减损术

原理:
两个正整数a和b(a>b),它们的最大公约数 = a-b的差值c和较小数b的最大公约数

步骤:
根据以上定理,不断把两个较大的整数之间的运算,简化成两个较小整数之间的运算,直到两个数相等为止,最大公约数就是最终相等的这两个数的值

分析:
更相减损术是不稳定的算法,依靠两数求差的方式来递归,运算次数远大于辗转相除法的取模方式

举例:
在这里插入图片描述

public int modifiedSubtraction(int a,int b){
        if (a==b)
                return a;
        int max = a>b?a:b;
        int min = a>b?b:a;
        return modifiedSubtraction(max-min,min);
    }

三:在更相减损术的基础上使用移位运算

以下分析中,gcd()为求最大公约数的方法
在这里插入图片描述
分析:
这种方法在两数都较小时,可能看不出计算次数的优势,但当两数越大时,计算次数的减少就会越明显,避免了取模运算,算法性能稳定,最坏时间复杂度为O(max(a,b))

//    移位运算
    public int shiftOperation(int a,int b){
        if (a==b)
            return a;
//        a b均为偶数
        if ((a&1)==0 && (b&1)==0)
            return shiftOperation(a>>1,b>>1)<<1;
//        a为偶数,b为奇数
        else if ((a&1)==0 && (b&1)!=0)
            return shiftOperation(a>>1,b);
//        a为奇数,b为偶数
        else if ((a&1)!=0 && (b&1)==0)
            return shiftOperation(a,b>>1);
//        a b为奇数
        else {
//       先更相减损一次
            int big = a>b?a:b;
            int small = a>b?b:a;
            return shiftOperation(big-small,small);
        }
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值