辗转相除法+更相减损法求最大公约数
来源:互联网 发布:淘宝化妆品店铺推荐 编辑:程序博客网 时间:2024/05/17 05:14
怎么求两个数的最大公约数呢?
简单的想法就是直接暴力枚举,试出最大公约数
暴力枚举
#暴力枚举def GCD(numberA,numberB): gcd=1 for i in range(2,max(numberA,numberB)+1): if numberA%i == 0 and numberB%i == 0: gcd=i return gcd
这显然不是一个好的算法,那么应该怎么优化呢?
辗转相除法
公元前300年前就有了这类问题的解法:辗转相除法, 又名欧几里得算法(Euclidean algorithm),目的是求出两个正整数的最大公约数。它是已知最古老的算法。
这条算法基于一个定理:两个正整数a和b(a>b),它们的最大公约数等于a除以b的余数c和b之间的最大公约数。比如10和25,25除以10商2余5,那么10和25的最大公约数,等同于10和5的最大公约数。
#辗转相除法——欧几里得算法'''两个正整数a和b(a>b),它们的最大公约数等于a除以b的余数c和b之间的最大公约数。比如10和25,25除以10商2余5,那么10和25的最大公约数,等同于10和5的最大公约数。 缺点:做a%b运算的时候效率比较低''' def GCD_Euclidean(numberA,numberB): gcd=1 if numberA>numberB: return getresult(numberA,numberB) else : return getresult(numberB,numberA) return gcddef getresult(big,small): if big%small is 0: return small else : return getresult(small,big%small)
更相减损法
但是在取模运算的时候效率很低,有没有什么办法优化呢?
中国古代的《九章算术》中就有了相应的办法:更相减损术,也是一种求最大公约数的算法。
它的原理更加简单:两个正整数a和b(a>b),它们的最大公约数等于a-b的差值c和较小数b的最大公约数。比如10和25,25减去10的差是15,那么10和25的最大公约数,等同于10和15的最大公约数
#更相减损术, 出自于中国古代的《九章算术》,也是一种求最大公约数的算法。'''两个正整数a和b(a>b),它们的最大公约数等于a-b的差值c和较小数b的最大公约数。比如10和25,25减去10的差是15,那么10和25的最大公约数,等同于10和15的最大公约数。缺点:如果两数相差很远,如10000 和 1就需要迭代很多次'''def GCD_jiuzhang(numberA,numberB): gcd=1 if numberA>numberB: return get_jiuzhang(numberA,numberB) else : return get_jiuzhang(numberB,numberA) return gcddef get_jiuzhang(numberA,numberB): if numberA is numberB: return numberA if numberA>numberB: return GCD_jiuzhang(numberB,numberA-numberB) else: return GCD_jiuzhang(numberB,numberB-numberA)
但是计算1000000和1的时候需要递归很多次,有没有什么办法优化呢?
此时应该将前面提到的,辗转相除法和更相减损术结合起来,在更相减损术的基础上用上移位运算
辗转相除法+更相减损法
众所周知,移位运算的性能非常快。对于给定的正整数a和b,不难得到如下的结论。
其中gcb(a,b)的意思是a,b的最大公约数函数:
当a和b均为偶数,gcb(a,b) = 2*gcb(a/2, b/2) = 2*gcb(a>>1, b>>1)
当a为偶数,b为奇数,gcb(a,b) = gcb(a/2, b) = gcb(a>>1, b) 偶数和奇数的最大公约数==奇数和偶数的一半的最大公约数
当a为奇数,b为偶数,gcb(a,b) = gcb(a, b/2) = gcb(a, b>>1)
当a和b均为奇数,利用更相减损术运算一次,gcb(a,b) = gcb(b, a-b), 此时a-b必然是偶数,又可以继续进行移位运算。
def GCD_Ecu_jiuzhang(numberA,numberB): gcd=1 if numberA>numberB: return get_Ecu_jiuzhang(numberA,numberB) else : return get_Ecu_jiuzhang(numberB,numberA) return gcddef get_Ecu_jiuzhang(numberA,numberB): if numberA is numberB: return numberA if numberA<numberB: return get_Ecu_jiuzhang(numberB,numberA)#保证每次都是前一个数大于后一个数 else: #都是偶数的情况 if numberA%2 == numberB%2 ==0: return get_Ecu_jiuzhang(numberA>>1,numberB>>1)<<1 #A是偶数,B是奇数 elif numberA%2==0 and numberB%2!=0: return get_Ecu_jiuzhang(numberA>>1,numberB) #A是奇数,B是偶数 elif numberB%2==0 and numberA%2!=0: return get_Ecu_jiuzhang(numberA,numberB>>1) #都是奇数 else: return get_Ecu_jiuzhang(numberA-numberB,numberB)
参考
https://juejin.im/post/5a217bac51882531926e8656?utm_source=gold_browser_extension
- 辗转相除法+更相减损法求最大公约数
- 求最大公约数-辗转相除法-更相减损术
- 最大公约数(辗转相除法和更相减损法)
- 求最大公约数——辗转相除法,更相减损术
- 求最大公约数之辗转相除法、更相减损术及两者结合算法
- 【C语言】最大公约数(更相减损法)和(辗转相除法)
- 辗转相除法、更相减损法、Stein算法
- C++算法:辗转相除法与更相减损术
- 辗转相除法求最大公约数
- 辗转相除法求最大公约数
- 辗转相除法求最大公约数
- 辗转相除法求最大公约数
- 求最大公约数-辗转相除法
- 辗转相除法求最大公约数
- 辗转相除法求最大公约数
- 【辗转相除法求最大公约数】
- 辗转相除法求最大公约数
- 辗转相除法求最大公约数
- 回文链表 请编写一个函数,检查链表是否为回文。 给定一个链表ListNode* pHead,请返回一个bool,代表链表是否为回文。 测试样例: {1,2,3,2,1} 返回:true {1,2,3,
- 018 参数估计之点估计法:矩估计法、最大似然估计
- 洛谷P3313 [SDOI2014]旅行
- VS配置Mysql和OpenGL
- mysql中倒入sql文件,source命令
- 辗转相除法+更相减损法求最大公约数
- CentOS下VMware用桥接模式,静态ip上外网
- centos6.5安装mysql5.7
- 1304因子求和
- TCP——停等ARQ&连续ARQ
- jQuery easyui datagrid扩展之颜色条
- 基于不确定性主动学习的基本过程
- jvm日志输出
- 集合学习总结二