package main
import "fmt"
/*
使用辗转相除法求两个数的最大公约数。
思路:辗转相除法原理为 a 和 b的最大公约数等于 b 和 a%b的最大公约数 (a > b) ,
依次类推把求a b 的最大公约数换算成较小的值来求
*/
func getGreatestCommonDivisorV1(a, b int) int {
// 首先要保证 a > b
if a < b {
temp := a
a = b
b = temp
}
if a%b == 0 {
return b
}
return getGreatestCommonDivisorV1(b, a%b)
}
/*
更相减损术求两个数的最大公约数
思路:更相减损术原理:a 与 b 的最大公约数等于 b 与 a-b的最大公约数 (a > b)
*/
func getGreatestCommonDivisorV2(a, b int) int {
// 首先要保证 a > b
if a < b {
temp := a
a = b
b = temp
}
if a%b == 0 {
return b
}
return getGreatestCommonDivisorV2(b, a-b)
}
/*
求最大公约数最优算法: 结合上面两个方法和移位运算
思路:
当a和b均为偶数,gcd(a,b) = 2 X gcd(a/2,b/2) = 2 X 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)
当都为奇数时。先利用更相减损术运算一次,gcd(a,b) = gcd(b, a-b), 此时a-b又变成偶数。然后又可以进行移位运算。
*/
func gcd(a, b int) int {
// 首先要保证 a > b
if a < b {
temp := a
a = b
b = temp
}
// 找到最大公约数的条件 a ==b
if a == b {
return a
}
// 1. a,b都为偶数
if a&1 == 0 && b&1 == 0 {
return gcd(a>>1, b>>1) << 1
} else if a&1 == 0 && b&1 != 0 { // 2. a为偶数b为奇数
return gcd(a>>1, b)
} else if a&1 != 0 && b&1 == 0 { // 3. a为奇数b为偶数
return gcd(a, b>>1)
} else { // 都为奇数
// 进行一次更相减损术运算
return gcd(b, a-b)
}
}
// test
func main() {
// 辗转相除法
num01 := getGreatestCommonDivisorV1(1992, 88)
fmt.Println(num01)
// 更相减损术
num02 := getGreatestCommonDivisorV2(1992, 88)
fmt.Println(num02)
// 最优解法
num03 := gcd(1992, 88)
fmt.Println(num03)
}
辗转相除法求最大公约数_求两个数额最大公约数的几种方法并对其优化
最新推荐文章于 2021-01-12 14:53:39 发布