• 求两个数字的最大公约数-Python实现,三种方法效率比较,包含质数打印质数的方法


    今天面试,遇到面试官询求最大公约数。小学就学过的奥数题,居然忘了!只好回答分解质因数再求解!

    回来果断复习下,常用方法辗转相除法更相减损法小学奥数都学过,很简单,就不细说了,忘了的话可以百度:http://baike.baidu.com/link?url=Ba106RbHkMjZm3rolmCHEEFt3eDkVbngcReykcqt4Wv0dbTI_0ZmTDE5b0X-xWFx

    以下是代码实现,这两种方法,还有常规的分解因式,顺便比较了一下效率,其中分解因式用了两种方法来求取小于该数字的所有质数,:

    #coding:utf-8
    import time
    #辗转相除法:
    def commonDivisor1(num1,num2):
        if num1 < num2:
            temp = num1
            num1 = num2
            num2 = temp
             
        if  num1%num2 ==0:
            return num2
        else:
            num2 = num1%num2
            return commonDivisor1(num1,num2)
    
    #更相减损法
    def commonDivisor2(num1,num2):    
        if num1==num2:return num1
        elif num1 < num2:
            temp = num1
            num1 = num2
            num2 = temp
        if num1 - num2 == num2:
            return num2
        else:
            temp = num1 
            num1 = num2
            num2 = temp - num2
            #print (num1,' ', num2)
            return commonDivisor2(num1,num2)
    
    #分解质因数,之后求解
    def commonDivisor3(num1,num2):
        if num1==num2:return num1
        elif num1 < num2:
            temp = num1
            num1 = num2
            num2 = temp  
        #求小于较小数字的所有素数   
        primeNum = getPrimeNumber1(num2)
        #print (primeNum)
        #对较小的数字分解质因数,并将质因数保存在l2中
        l2 = []
        result = 1 
        while num2 != 1:
            for i in primeNum:
                if num2 % i !=0:
                    continue
                else:
                    l2.append(i)
                    num2 = num2 / i 
        #print ('l2: ',l2)
        #使用较大数字去除较小数字的质因数,看大数字中包含了哪些较小数字的质因数。
        #将大数字也包含的相同的质因数相乘返回结果,即最大公约数
        for i in l2:
            if num1 % i == 0:
                result = result*i
                num1 = num1/i
        return result
    
    #分解质因数,之后求解
    def commonDivisor4(num1,num2):
        if num1==num2:return num1
        elif num1 < num2:
            temp = num1
            num1 = num2
            num2 = temp  
        #求小于较小数字的所有素数   
        primeNum = getPrimeNumber2(num2)
        #print (primeNum)
        #对较小的数字分解质因数,并将质因数保存在l2中
        l2 = []
        result = 1 
        while num2 != 1:
            for i in primeNum:
                if num2 % i !=0:
                    continue
                else:
                    l2.append(i)
                    num2 = num2 / i 
        #print ('l2: ',l2)
        #使用较大数字去除较小数字的质因数,看大数字中包含了哪些较小数字的质因数。
        #将大数字也包含的相同的质因数相乘返回结果,即最大公约数
        for i in l2:
            if num1 % i == 0:
                result = result*i
                num1 = num1/i
        return result
    
    #列出小于num的所有奇数,首先去除可以被2整除的,再去除可以被3整除的,再去除可以被5整除的,以此类推...           
    def getPrimeNumber1(num):
        l = [2]
        for i in range(3,num+1,2):
            l.append(i)
        j = min(l)
        while not j == l[-1]:
            for k in l:
                if (k%j==0) and k != j:
                    #print ('remove: ',k)
                    l.remove(k)
            #print (l,' ',j)
            j = l[l.index(j)+1]
        return l
    
    #用生成器和filter求num以内的所有质数
    def getPrimeNumber2(num):
        l=[]
        for n in primes():
            if n < num:
                l.append(n)
            else:
                break
        return l
    
    #创建打印奇数的生成器
    def _odd_iter():
        n = 1
        while True:
            n = n + 2
            yield n
    
    #创建过滤条件,即过滤掉可以被列表中下一个数字整除的数字,留下不可以被这个数整除的,即留下质数
    def _not_divisible(n):
        return lambda x: x % n > 0
    
    #不断迭代生成列表,根据规则过滤掉列表中元素,留下质数
    def primes():
        yield 2
        it = _odd_iter() # 初始序列
        while True:
            n = next(it) # 返回序列的第一个数
            yield n
            it = filter(_not_divisible(n), it) # 构造新序列
      
    time1 = time.clock()
    print (commonDivisor1(12355,525))
    time2 = time.clock()
    print (commonDivisor2(12355,525))
    time3 = time.clock()
    print (commonDivisor3(12355,525))
    time4 = time.clock()
    print (commonDivisor4(12355,525))
    time5 = time.clock()
    
    print ('辗转相除法用时: ', (time2-time1)*1000,'')
    print ('更相减损法用时: ', (time3-time2)*1000,'')
    print ('分解质因数法用时(用列表求质数): ', (time4-time3)*1000,'')
    print ('分解质因数法用时(用生成器求质数): ', (time5-time4)*1000,'')

     测试结果:

    随便测试两个数字,发现辗转相除法明显是最快的,原因也很明显,计算次数明显比更相减损法少,传统分解因式方法,那效率自然不用说了。

    35
    35
    35
    35
    辗转相除法用时:  0.014617272401167485 秒
    更相减损法用时:  0.15565419800162134 秒
    分解质因数法用时(用列表求质数):  9.131449575150953 秒
    分解质因数法用时(用生成器求质数):  8.505277230398239 秒
  • 相关阅读:
    mac下编写命令脚本
    mac环境mongodb安装小坑
    JS
    设计模式:装饰器
    proxy 数据帧听
    react hook 简单实现
    报错:java.lang.NumberFormatException: null
    git回滚到指定版本
    1109. 航班预订统计 力扣(中等) 差分数组 不会但神奇
    528. 按权重随机选择 力扣(中等) 前缀和rand()
  • 原文地址:https://www.cnblogs.com/yuanzhaoyi/p/6111455.html
Copyright © 2020-2023  润新知