最近发现在搞Android的都要懂一点数据结构和算法才能进阶到高手,所以就回去复习了一下基础,为一些公司招聘做题做准备。
今天研究了一下最大公约数的求法,在网上也找了不同的解法,现在就想总结一下,拿出来分享给大家,共同 学习
首先讲一个什么是公约数,这个问题我们小学都学过,可能有一部分人已经忘记了,所以还是讲一下,假设有两个数a,b,所谓的公约数就是能把a,b整除的最大整数。

明白了要求我们就来解决问题,一拿到问题我们都应该都能想到一个方法,就是使用穷举法,从2开始一个个找,到一个两个都能除的就记录起来,一直找到小于min(a,b)结束,
记录到的值就是他们的最大公约数代码由下:

?
代码片段,双击复制
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
//找出最大公约数,穷举法
        public static int getMaxDivide_ab(int a,int b){
                int value=1;
                int max;
                int min;
                if(a==b){
                        return a;
                }
                if(a>b){
                        max=a;
                        min=b;
                }else{
                        max=b;
                        min=a;
                }
                for(int i=2;i<min;i++){
                        if(0==max%i && 0==min%i){
                                value=i;
                        }
                }
                return value;
        }

第二种方法是使用欧几里德算法,这个已经有2000+年的历史了,这个比起上一个来的要高效,假设我们的最大公约数表示为f(a,b),并且有a>=b>0,
欧几里德就给了我们一个很好的定理,f(a,b)=f(b,a%b),有了这个等式我们就很容易得出这个算法的递归式,现在我们来看下这个等式是怎么来的
设有 r=a/b ,q=a%b  
所以就有 a=a/b*b+q  ----(这里的a/b*b!=a   ,原因就是我们用的是整数来计算的)
也就是a=r*b+q     变换一下有:q=a-r*b      设d=f(a,b),a/d=m,b/d=n;则  有q=dm-r*dn=d(m-rn)
所以q/d也为0;设d|q表示d是q的约数;以下相同;
又有d|b;所以有d|(b,q),设D是(b,q)的最大公约数,则会有d<=D=f(b,q);

再回到前面r=a/b,q=a%b这两个条件有
a=r*b+q,由于D|(b,q),所以D|a,所以有D|(a,b)
所以有D<=d=f(a,b),结合上部分就有d<=D <+d,及D=d;
所以得证;
代码实现由下:

?
代码片段,双击复制
01
02
03
04
05
06
07
08
09
10
11
12
public static int oujilide(int a,int b){
                if(a<b){
                        int temp;
                        temp=a;
                        a=b;
                        b=temp;
                }
                if(0==b){
                        return a;
                }
                return oujilide(b,a%b);
        }

第三种方法是上一种的变形

我们在对大整数求最大公约数,第二种方法的效率就出现了瓶颈,实际上对于大整数而言,取模运算(用到除法)的开销非常的昂贵,这就是欧几里得算法的局限性,那么我们就得优化一下它了,借鉴欧几里得的辗转相除法,既然是取模运算导致的问题,那么我们就不用取模运算,换用“-”运算,即 f(x,y)=f(x-y,y);深入考虑一下发现在算法运行的过程可能会出现x<y的情况,这时候要交换x和y,但是结果不受影响。 
这个方法的证明可以看上面一种给出的证明,细想一下都是一样的
实现代码也很简单:

?
代码片段,双击复制
01
02
03
04
05
06
07
08
09
10
11
12
public static int xymod(int a,int b){
                if(a<b){
                        int temp;
                        temp=a;
                        a=b;
                        b=temp;
                }
                if(0==b){
                        return a;
                }
                return xymod(a-b,b);
        }

在算法的效率上第二种和第三种都有个自的局限性,一个在大整数上,一个在迭代上, 我们还可以找到一个综合上面两种的算法就是,一步步的简化a,b这两个数,简化的方法由下:

(1)如果y=k*y1,x=k*x1.那么有f(x,y)=k*f(x1,y1)
(2)如果x=p*x2,p为素数,并且y%p != 0,那么f(x,y) = f(p*x2,y) = f(x2,y)
于是我们得到下面的解决方法:
将p = 2,
若x,y均为偶数,f(x,y) = 2*f(x/2,y/2) = 2*f(x>>1,y>>1);
若x是偶数,y是奇数,f(x,y) = f(x/2,y) = f(x>>1,y);
若x是奇数,y是欧式,f(x,y) = f(x,y/2) = f(x,y>>1);
若x和y均为奇数,f(x,y) = f(y,x-y)。这时x-y一定是偶数,下一步一定会除以2。

上面的方法来源都可以用到上面的证明过程,
代码实现由下:

?
代码片段,双击复制
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public static int moveCombe(int a,int b){
                if(a<b){
                        return moveCombe(b, a);
                }
                if(0==b){
                        return a;
                }
                if(isTwo(a)){
                        if(isTwo(b)){
                                return moveCombe(a/2, b/2)*2;
                        }
                        return moveCombe(a/2, b);
                }else{
                        if(isTwo(b)){
                                return moveCombe(a, b/2);
                        }
                        return moveCombe(b, a-b);
                }
                         
                         
        }
        private static boolean isTwo(int a) {
                if(0==a%2){
                        return true;
                }else{
                        return false;
                }
        }

上面的代码都比较简单,我就没有做注解了,这些思想大部分都来自了网络,代码自己重写过,有不对之处还请大家指出,共同学习。

全部代码:

转载于:https://www.cnblogs.com/hexiaochun/archive/2012/09/03/2668250.html

java 算法基础之一寻找最大公约数相关推荐

  1. Java算法基础:使用递归算法实现,平方相加1^2 + 2^2 + 3^2 +...+ n^2。

    package algorithm.recursion; public class RecursionTest {public static void main(String[] args) {int ...

  2. C/C++ 算法基础

    如果要真正掌握算法,必须要写代码的,那这时候就必须选择一门语言来进行,而具体的语言其实无所谓 ,C.C++.Java.Python,go甚至JavaScript.VB都可以,关键是自己要用的熟悉,面试 ...

  3. Java算法--第二章--查找与排序(2)递归基础--佩波那契最大公约数插入排序汉诺塔

    Java算法–第二章–查找与排序(2)递归基础 一.找重复 1.找到一种划分方法 2.找到递推公式或者等价转换 都是父问题转化为求解子问题 二.找变化的量 变化的量通常要作为参数 三.找出出口 代码: ...

  4. 算法基础、算法比赛快速入门(java)

    想用Java快速入门算法?这篇文章你得看! 提示:本文章适合想要入门算法,并且想 "快速" 达到一定成果的同学们阅读~ 文章非常非常非常长(可能是你见过最长的算法基础篇章)!!! ...

  5. 数据结构与算法基础(java版)

    目录 数据结构与算法基础(java版) 1.1数据结构概述 1.2算法概述 2.1数组的基本使用 2.2 数组元素的添加 2.3数组元素的删除 2.4面向对象的数组 2.5查找算法之线性查找 2.6查 ...

  6. 【数据结构与算法基础】并查集原理、封装实现及例题解析(C和java)

    前言 数据结构,一门数据处理的艺术,精巧的结构在一个又一个算法下发挥着他们无与伦比的高效和精密之美,在为信息技术打下坚实地基的同时,也令无数开发者和探索者为之着迷. 也因如此,它作为博主大二上学期最重 ...

  7. 【Java面试高频问题】Java数据结构和算法基础知识汇总

    文章目录 Java数据结构和算法基础知识 一.Java数据结构 1. 线性结构:数组.队列.链表和栈 1.1 数组(Array) 1.2 稀疏数组 1.3 队列(Queue) 1.4 链表(Linke ...

  8. 算法每日学打卡:java语言基础题目打卡(01-10)

    文章有不当之处,欢迎指正,如果喜欢微信阅读,你也可以关注我的微信公众号:好好学java,获取优质学习资源. "算法每日学"计划01打卡: 问题描述 对于长度为5位的一个01串,每一 ...

  9. Java寻找最大公约数

    Java寻找最大公约数 利用欧几里得除法可以很容易的到的 循环实现 public static void main(String[] args) {Scanner scan = new Scanner ...

最新文章

  1. MySQL主从复制配置过程(一主一从模式)
  2. 计算机专业活动简报,计算机系辩论赛活动简报
  3. Laravel 框架安装
  4. 第四讲 一阶线性ODE换元法
  5. JavaScript-4.2函数,变量作用域---ShinePans
  6. Redhat 6.4_联网 yum 配置
  7. php安装solr扩展,PHP扩展模块 solr 安装
  8. 雷兽的数据库CAP乱谈之(一)阐述
  9. thinking-in-java(20)注解
  10. java zoneoffset,java - 如何在java8中获取默认的ZoneOffset? - SO中文参考 - www.soinside.com...
  11. Android 系统(250)---main log导入到uart口
  12. MySQL优化索引及优化汉字模糊查询语句
  13. mac上远程连接windows
  14. Linux的哲学思想
  15. 杭电 1272 并查集判断环
  16. 【物理应用】基于matlab Q学习无线体域网路由方法【含Matlab源码 264期】
  17. mc2180 刷机方法_MC控制和时差方法
  18. springboot的错误页面配置
  19. 测量平差个人知识总结
  20. 安徽建立“库长制” 千余名库长保粮食安全

热门文章

  1. eclipse安装反编译插件:jd-eclipse 查看源码
  2. oracle11g远程命令执行漏洞,漏洞应急|Oracle Weblogic Server远程代码执行漏洞(CVE-2021-2109)...
  3. MySQL 读写分离 部分_一个完整的mysql读写分离环境包括以下几个部分
  4. java实现所有括号组合的遍历_括号正确嵌套问题的实现(Java)
  5. R语言作图之ggplot2初识(1)
  6. latex转为html效果好吗,latex2html
  7. R语言与机器学习学习笔记(分类算法)
  8. 系统学习深度学习(二十四)--WRN
  9. 系统学习机器学习之随机场(五)--CRF++源码L-BFGS算法补充
  10. 已知坐标求方位角_震惊,up主居然能默写球坐标拉普拉斯算子!