求兩個數的最大公約數,輾轉相除法與更相減損法(遞歸叠代)
阿新 • • 發佈:2018-07-27
叠代 div 余數 公約數 穩定 log test 算法 復雜度
問題:給出兩個數a和b,求出他們的最大公約數(greatest common divisor)。
解法一:輾轉相除法,又叫歐幾裏得算法。兩個正整數a和b(a>b),他們的最大公約數等於a除以b的余數和b之間的最大公約數。
比如10和25,25除以10余5,那麽10和25的最大公約數等同於5和10之間的最大公約數。
//輾轉相除法 遞歸解法 int gcd(int a,int b){ if(a%b==0) return b; return (b,a%b); }
//輾轉相除法 叠代解法
int gcd2(int a,int b){ int t;while(b!=0){ t=b; b=a%b; a=t; } return a; }
解法二:更相減損術,出自中國古代的《九章算術》。兩個正整數a和b(a>b),他們的最大公約數等於a-b的差值c和較小數b的最大公約數。
比如10和25,25-10=15,那麽10和25的最大公約數等於10和15的最大公約數。
//更相減損術 遞歸 int gcd3(int a,int b){ if(a==b) return a; if(a>b) return gcd(a-b,b);else return gcd(b-a,a); }
//更相減損術 叠代 int gcd4(int a,int b){ while(a*b!=0){ if(a>b) a=a-b; else b=b-a; } return a?a:b; }
改進:更相減損術是不穩定的算法,當兩個數相差懸殊時,如10000和1的最大公約數,要遞歸9999次。
做法;
當a和b都是偶數時,gcd(a,b)=2*gcd(a/2,b/2)=2*gcd(a>>1,b>>1)。
當a是奇數,b是偶數時,gcd(a,b)=gcd(a,b/2)=gcd(a,b>>1)。
當a是偶數,b是奇數時,gcd(a,b)=gcd(a/2,b)=gcd(a>>1,b)。
當a和b都是奇數數時,gcd(a,b)=gcd(a-b,b)。
//改進版: int gcd5(int a,int b){ if(a==b) return a; else if(a<b) return gcd5(b,a); //始終讓 a>b else{ if(!(a&1)&&!(b&1)){ //兩數都為偶數 return gcd5(a>>1,b>>1)<<1; }else if((a&1)&&!(b&1)){ //a奇數 b偶數 return gcd5(a,b>>1); }else if(!(a&1)&&(b&1)){ //a偶數 b奇數 return gcd5(a>>1,b); }else return gcd(a,a-b); //都是奇數 相減 } }
算法復雜度:
輾轉相除法:O(log(max(a,b)))
更相減損法:O(max(a,b))
改進更相減損法:O(log(max(a,b)))
求兩個數的最大公約數,輾轉相除法與更相減損法(遞歸叠代)