题解 | #最大公约数#

最大公约数

http://www.nowcoder.com/practice/cf4091ca75ca47958182dae85369c82c

题目陈述

题目大意:求正整数a,b的最大公约数x
仔细审题:最大公约数,即不存在一个比x大,且同时能整除整数a,b的正整数

算法一:暴力做法

算法思路

  1. mi=min(a,b),即mi为a,b中较小的那个数字
  2. for循环暴力求解,i从1开始循环,到mi截至(因为不存在因数比原数字大的情况),如果能整除,则将i记录到c中
  3. 最后返回c,因为i是递增的,最后返回的也一定是最大的那个数字
  4. 时间复杂度为,这边a,b最大可以到1e9,但是数据很弱,我试了一下,特判a,b是否能整除对方的情况,再for循环,可以AC……(还是学正解吧)

    代码实现

    class Solution {
    public:
     int gcd(int a, int b) {
         int c=1,mi=min(a,b);//Mi为a,b中较小的那个数
         if(a%b==0)return b;//判断一个数是否是另一个数字的整数倍
         if(b%a==0)return a;
         for(int i=2;i<=mi;i++){
             if(a%i==0&&b%i==0){//i为ab的公约数
                 c=i;
             }
         }
         return c;
     }
    };

    算法二:辗转相减法

    算法思路

    1、(先讲思路,待会给大家简单证明一下算法的正确性)
    2、此处设a>b,gcd(a,b)表示为a,b的最大公约数,求解gcd(a,b),等价于求解gcd(b,a- b),当其中一个数为0的时候,即gcd(a,0),答案就是a
    3、递归反复执行上述操作,就能得到gcd(a,b)

    证明:算法正确性

  • 设有整数x,若,,设,则那么有,即
  • 即a,b的约数也是c的约数,所以a,b的gcd,也必然是c的约数
  • 算法正确性得证
  1. 但是理论上来说,这个算法的时间复杂度依旧可以达到O(n),博主造了一组数据(不用数了,9个零),这种情况,我们就需要执行次操作,依旧会超时
  2. 但是题目数据很弱,程序还是过了……(过了不代表对哦,还是需要学会正解)
  3. 时间复杂度,此处肯定有同学好奇了,这个算法怎么比上一个算法时间复杂度还大?那我学他干嘛?
  4. 注意,O(***)代表的是最坏时间复杂度,我们一般分析的是最坏时间复杂度,但是一般情况下,我们遇到的平均时间复杂度,可以理解为算法2大部分情况比算法1优,但是在某种情况下面他甚至没有算法1优

    代码实现

    class Solution {
    public:
     int gcd(int a, int b) {
        if(a<b)swap(a,b);//保证a比b大,不然就会出现a-b是负数,gcd(a,b)等价于gcd(b,a)
         return !b?a:gcd(b,a-b);//b为0返回a,否则返回a-b
     }
    };

    算法三:辗转相除法

    算法思路

  5. 相比于前两个算法,这个算法已经足以过掉任何强的数据了
  6. ,直到b为0的时候,a即为答案,如何理解呢?
  7. 这边就不数学证明了,毕竟对于刚开始学习算法的小白,我们可以基于上面的证明“感性理解”,毕竟有些东西证明不需要特别严谨。
  8. 在上面的算法二中,对于gcd(9,2),会执行,(下面省略交换a,b的过程,默认大的数字在前面)最后返回1,
  9. 我们会发现前面一直执行这个减去2的操作,很耗时间,最后要取到的1,不过是9除以2的余数,即9%2,所以这一过程我们用a%b来代替a-b
  10. 不难理解,算法二中,什么时候会交换a,b?即反复执行a-b,直到a比b小的情况,那么这个不就是,a除以b的余数吗?
  11. 时间复杂度,有一篇论文证明过,过于繁琐,此处不展开,有兴趣的同学建议上网百度

    动画演示

    图片说明

代码实现

C++

class Solution {
public:
    int gcd(int a, int b) {
        return !b?a:gcd(b,a%b);
        //为a<b的情况,a%b依旧等于,即gcd(b,a%b)<==>gcd(b,a)相当于交换a,b,所以此处不用写swap
    }
};

Python

class Solution:
    def gcd(self , a , b ):
        if b==0:
            return a
        else :
            return self.gcd(b,a%b)
全部评论

相关推荐

小厂面经,也是我的处女面(30min)1.自我介绍2.spring&nbsp;boot的自动装配原理(好多类和接口的单词都忘了全称是啥了,就说了记得的单词,流程应该说对了吧)3.有用过redis吗?主要是用在实现什么功能(说了技术派用redis的zset来实现排行榜)5.有了解过Redisson吗?讲一下对于分布式锁的了解以及在什么场景下应用(说了秒杀场景)6.对mysql有了解吗?包括它的索引优化和创建(把想起来的全说了)7.了解设计模式吗?比如单例模式,为什么要使用单例模式,它的优点是什么(昨天刚看的设计模式)8.工厂模式有了解吗?主要的使用场景是?(也是昨天刚看的)9.场景题:有7个服务器,需要在早上十点定时的向数据库中的用户表中的用户发短信,如果做到发送的消息不重复,且如果发送失败了需要知道是到哪个用户失败了,这样下次就直接从这个用户开始(我答了用spring&nbsp;task来实现定时,用分布式锁来保证只有一份服务器可以发送消息,用消息队列来存储消息,然后用消息确认机制来保证错误信息的记录,以及在数据库或者业务层面完成消息消费的幂等性)10.场景题:如果在系统启动的时间就将数据库的所有用户相关的信息都读到一个hashmap中(这个没啥思路,没答好)27届的投了一个星期终于有一个面试了,大部分公司都只招26的
inari233:已oc,拒了
查看9道真题和解析
点赞 评论 收藏
分享
no_work_no_life:深圳,充电宝,盲猜anker
点赞 评论 收藏
分享
评论
26
5
分享

创作者周榜

更多
牛客网
牛客企业服务