时间复杂度小的 求两个整数的最大公约数
简单回顾一下时间复杂度:
一个算法是由控制结构(顺序、分支和循环三种)和原操作(指固有数据类型的操作)构成的,则算法时间取决于两者的综合效果。
为了便于比较同一问题的不同算法,通常的做法是,从算法中选取一种对于所研究的问题(或算法类型)来说是基本操作的原操作,以
该基本操作重复执行次数作为算法的时间量度。
最近刷一道PAT的题目时,总有两个测试点超时,原来是自己的代码时间复杂度太大了。撰写此文,谨记!
求两个整数的最大公约数。
一:辗转相除法(欧几里德算法 出自几何原本)
基本原理和证明不在这里考究证明,(感觉其实是证明了gcd(a,b)=gcd(b,r),r是a mod b的结果)有兴趣的可以看看百度百科。辗转相除法
1 int gcd0(int a,int b) //辗转相除法接地气的一种写法 2 { 3 int r=1; 4 while(r!=0) 5 { 6 r=a%b; 7 a=b; 8 b=r; 9 } 10 return a; 11 } 12 int gcd(int a,int b) //辗转相除法高大上的一种写法 13 { 14 return (b>0)?gcd(b,a%b):a; 15 }
二:更相减损法 (出自《九章算术》)
1 int gcd3(int a,int b) //更相减损法 2 { 3 int n=1; //存储第一步中约掉的若干个2 1代表2^0 即0个2 4 int ans; //存储最终返回的结果 5 while(a%2==0&&b%2==0) 6 { 7 a/=2;b/=2;n*=2; 8 } 9 while(a!=b) 10 { 11 if(a>b) 12 a-=b; 13 else 14 b-=a; 15 } 16 ans*=a*n; 17 return ans; 18 }
一下是总结的三种求最大公约数的三种方法的代码
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 int gcd0(int a,int b) //穷举法 5 { 6 int i; 7 for(i=min(a,b);i>0;i--) 8 { 9 if(a%i==0&&b%i==0) 10 break; 11 } 12 return i; 13 } 14 15 int gcd1(int a,int b) //辗转相除法接地气的一种写法 16 { 17 int r=1; 18 while(r!=0) 19 { 20 r=a%b; 21 a=b; 22 b=r; 23 } 24 return a; 25 } 26 int gcd2(int a,int b) //辗转相除法高大上的一种写法 27 { 28 return (b>0)?gcd2(b,a%b):a; 29 } 30 31 int gcd3(int a,int b) //更相减损法 32 { 33 int n=1; //存储第一步中约掉的若干个2 1代表2^0 即0个2 34 int ans; //存储最终返回的结果 35 while(a%2==0&&b%2==0) 36 { 37 a/=2;b/=2;n*=2; 38 } 39 while(a!=b) 40 { 41 if(a>b) 42 a-=b; 43 else 44 b-=a; 45 } 46 ans*=a*n; 47 return ans; 48 } 49 50 int main() 51 { 52 int a,b; 53 printf("请输入两个整数:"); 54 scanf("%d%d",&a,&b); 55 cout<<gcd3(a,b)<<endl; 56 cout<<gcd0(a,b)<<endl; 57 return 0; 58 }