算法分析与设计实验——最大公约数

最大公约数

取函数名为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),且递归次数过多也将占用过多的栈,不太稳定。

猜你喜欢

转载自blog.csdn.net/linyiduo123/article/details/79619982