今天面試,遇到面試官詢求最大公約數。小學就學過的奧數題,竟然忘了!只好回答分解質因數再求解!面試
回來果斷複習下,經常使用方法展轉相除法和更相減損法,小學奧數都學過,很簡單,就不細說了,忘了的話能夠百度:http://baike.baidu.com/link?url=Ba106RbHkMjZm3rolmCHEEFt3eDkVbngcReykcqt4Wv0dbTI_0ZmTDE5b0X-xWFxapp
如下是代碼實現,這兩種方法,還有常規的分解因式,順便比較了一下效率,其中分解因式用了兩種方法來求取小於該數字的全部質數,:測試
#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,'秒')
測試結果:url
隨便測試兩個數字,發現展轉相除法明顯是最快的,緣由也很明顯,計算次數明顯比更相減損法少,傳統分解因式方法,那效率天然不用說了。spa
35353535展轉相除法用時: 0.014617272401167485 秒更相減損法用時: 0.15565419800162134 秒分解質因數法用時(用列表求質數): 9.131449575150953 秒分解質因數法用時(用生成器求質數): 8.505277230398239 秒