思路:
题目的主要信息:
- 找到两个数a与b的最大公约数
- a与b最小为1,无特殊情况
最常规的求公因数,以下罗列几种方法。
方法一:穷举法
具体做法:
优先考虑a与b一个是另一个因子的情况,可以直接返回。
然后找到较小值,由小到大穷举2到较小值的所有数字,遇到公约数更新答案。
class Solution { public: int gcd(int a, int b) { if(a % b == 0) //当一个数是另一个数因数时 return b; if(b % a == 0) return a; int n = a > b ? b : a; //等于较小值 int res = 1; for(int i = 2; i < n; i++){ //穷举到较小值 if(a % i == 0 && b % i == 0) //公因数 res = i; } return res; } };
复杂度分析:
- 时间复杂度:,a与b即为两个数的大小
- 空间复杂度:,无额外空间使用
方法二:辗转相除法
具体做法:
依赖于欧几里得算法,相互大数除小数取余,然后小数再除余,到0为止。
class Solution { public: int gcd(int a, int b) { if(a % b == 0) //当一个数是另一个数因数时 return b; if(b % a == 0) return a; int temp; //比较两个数的大小,值大的数为a,值小的数为b if (a < b) { temp = a; a = b; b = temp; } //求余 while (b != 0) { temp = a % b; a = b; b = temp; } return a; } };
复杂度分析:
- 时间复杂度:,欧几里得算法是指数增长的
- 空间复杂度:,无额外空间使用
方法三:更相减损法
有一个性质:两个数的最大公约数等于它们中较小的数和两数之差的最大公约数。
具体做法:
模拟上述过程即可。
class Solution { public: int gcd(int a, int b) { int temp = abs(a - b); //取差的绝对值 while(temp != 0) //不断减去差的绝对值直到为0 { a = b; b = temp; temp = abs(a - b); } return b; } };
复杂度分析:
- 时间复杂度:最坏情况为,最坏一个一个减,全部减完
- 空间复杂度:,无额外空间