最大公约数
取函数名为gcd(a,b),假定a>b
方法一:暴力求解法
伪代码:
gcd(a,b)
for 1←b to i
if (a mod i==0) and (b mod i==0)
return i
C++代码:
#include <iostream>
using namespace std;
int min(int a,int b){
return a>b?b:a;
}
int gcd(int a,int b){
for(int i=min(a,b);i>=1;i--){
if(a%i==0&&b%i==0){
return i;
}
}
}
int main(){
int a,b;
cin>>a>>b;
cout<<gcd(a,b);
return 0;
}
此方法采取蛮力思想,从a、b之中较小数开始递减,一旦出现同为两数的因数的数,gcd函数即返回该因数。假定a>b,则最坏时间复杂度为O(b)。
该方法还可以进行简单的优化,如下:
gcd(a,b)
for 1←b/2 to i
if (a mod i==0) and (b mod i==0)
return i
将循环起始值设为b/2,可减少循环次数,在数据较大时可略微节省时间。
方法二:辗转相除法
gcd(a,b)
while temp!=0 do
temp=a mod b
a=b
b=temp
return a
辗转相除法又名欧几里得算法,C++代码如下(仅gcd函数):
int gcd(int a,int b){
int temp;
while(temp!=0){
temp=a%b;
a=b;
b=temp;
}
return a;
}
该函数还可运用递归进行简化:
int gcd(int a,int b){
return a%b==0?b:gcd(b,a%b);
}
该方法的时间复杂度为O(lgb),相比蛮力法节省了大量时间。但由于数据过大时取模运算性能较差,因此不适合进行大数的最大公约数求值。
方法三:更相减损法
伪代码:
gcd(a,b)
if a==b
return a
if a<b
return gcd(b-a,a)
else
return gcd(a-b,b)
C++代码(仅gcd函数):
int gcd(int a,int b){
if(a==b) return a;
if(a<b) return gcd(b-a,a);
else return gcd(a-b,b);
}
该方法运用两数求差的方法来优化大数运算时的性能。但在两数大小相差过大时,此方法的效率将十分低下,譬如a=1,b=100时,将进行99次递归,最坏时间复杂度甚至接近O(a),且递归次数过多也将占用过多的栈,不太稳定。