其实是求a、b(a>b)最大公约数。
(leetcode 1979. 找出数组的最大公约数)
方法一:遍历,遍历的思想就是从2开始到b(或者b/2)结束,如果其中某个数都能被两者整除,那该数就是最大公约数。
nums=[a,b]
A_max = max(nums)
B_min = min(nums)
int greatestCommonDivisor = 1;
for i in range(2,b+1):if A_max%i==0 and B_min%i==0:greatestCommonDivisor = i
方法二:辗转相除法
定理:两个正整数a、b(a>b)的最大公约数就是b和a%b(a除以b的余数)的最大公约数。
边界是当余数为0时最大公约数为另一个数。
class Solution:def findGCD(self, nums: List[int]) -> int:def gcd(a,b): #a>bif b==0:return aelse:return gcd(b, a%b)BigNum, SmallNum = max(nums), min(nums)return gcd(SmallNum, BigNum%SmallNum)
方法三:更相减损法
定理:两个正整数a、b(a>b)的最大公约数就是b和a-b的最大公约数。
边界是当差为0时最大公约数为另一个数。
class Solution:def findGCD(self, nums: List[int]) -> int:BigNum, SmallNum = max(nums), min(nums)def gcd(a,b):if a == b:return aelif a > b:return gcd(b, a-b)else:return gcd(a, b-a)return gcd(SmallNum, BigNum)
方法四:结合辗转相除法和更相减损法(主要是取模操作可以用移位替代),分情况讨论:
- 如果a和b都是偶数,那么
gcd(a,b)=2*gcd(a/2,b/2)=2*gcd(a>>1,b>>1)
- 如果a是偶数,b是奇数,那么
gcd(a,b)=gcd(a/2,b)=gcd(a>>1,b)
- 如果a是奇数,b是偶数,那么
gcd(a,b)=gcd(a,b/2)=gcd(a,b>>1)
- 如果a和b都是奇数,那么
gcd(a,b)=gcd(a,a-b)
,然后此时a-b一定是偶数,又可以进行移位操作。
class Solution:def findGCD(self, nums: List[int]) -> int:BigNum, SmallNum = max(nums), min(nums)def gcd(a,b):if a == b:return aelse:#与1做按位操作判断奇偶if ~a&1 and ~b&1:return 2*gcd(a>>1,b>>1)elif ~a&1 and b&1:return gcd(a>>1,b)elif a&1 and ~b&1:return gcd(a,b>>1)else:return gcd(b, a-b)return gcd(BigNum, SmallNum)