python辗转相除法最大公约数和最小公倍数_2020-09-12:手撕代码:最小公倍数,复杂度多少?...

福哥答案2020-09-12:

最大公约数

1.【更相减损法】=【等值算法】,避免了取模运算,但是算法性能不稳定,最坏时间复杂度为O(max(a, b)))。

2.【辗转相除法】,迭代和递归,时间复杂度不太好计算,可以近似为O(log(max(a, b))),但是取模运算性能较差。

3.【Stein算法】,不但避免了取模运算,而且算法性能稳定,时间复杂度为O(log(max(a, b)))。

4.【试除法】,时间复杂度是O(min(a, b)))。

两个数的最小公倍数

1.【利用最大公约数】。时间复杂度是O(最大公约数)。

2.【试乘法】。时间复杂度是O(min(a, b)))。

n个数的最小公倍数

1.【遍历法】,时间复杂度是O[n*O(最大公约数)]。

2.【二分法】,分桶法中的一种。并行和非并行。时间复杂度是O[n*O(最大公约数)]。

代码用go语言编写,代码如下:

package test39_lcmimport (    "fmt"    "testing")//go test -v -test.run TestLcmfunc TestLcm(t *testing.T) {    fmt.Println("----最大公约数")    fmt.Println(Gcd1(36, 42), "    1.更相减损法")    fmt.Println(Gcd2(36, 42), "    2.辗转相除法")    fmt.Println(Gcd3(36, 42), "    3.Stein算法")    fmt.Println(Gcd4(36, 42), "    4.试除法")    fmt.Println("----两个数的最小公倍数")    fmt.Println(Lcm1(36, 42), "    1.利用最大公约数")    fmt.Println(Lcm2(36, 42), "    2.试乘法")    fmt.Println("----N个数的最小公倍数")    fmt.Println(LcmN1([]int{2, 4, 6, 8}), "    1.遍历法")    fmt.Println(LcmN2([]int{2, 4, 6, 8}), "    2.二分法")}//1.最大公约数:【更相减损法】=【等值算法】func Gcd1(a int, b int) int {    k := 1    //这段代码其实可以不用的,但是算法介绍里有除以2的操作,故有这段代码    if true {        for a&1 == 0 && b&1 == 0 {            a /= 2            b /= 2            k <<= 1        }    }    //两数相减    for a != b {        //保证第一个数大于等于第二个数        if a < b {            a, b = b, a        }        a, b = b, a-b    }    return b * k}//2.最大公约数:【辗转相除法】func Gcd2(a int, b int) int {    if true {        //迭代        for b != 0 {            a, b = b, a%b        }        return a    } else {        //递归        if a%b == 0 {            return b        } else {            return Gcd2(b, a%b)        }    }}//3.最大公约数:【Stein算法】func Gcd3(a int, b int) int {    k := 1    //最大公约数跟系数k有关,不能省略    for a&1 == 0 && b&1 == 0 {        a /= 2        b /= 2        k <<= 1    }    for a != b {        //a和b,做除以2的操作        for a&1 == 0 {            a >>= 1        }        for b&1 == 0 {            b >>= 1        }        //a和b经过除以2的操作后,可能相等了        if a == b {            break        }        //保证第一个数大于等于第二个数        if a < b {            a, b = b, a        }        //做减法操作        a, b = b, a-b    }    return a * k}//4.最大公约数:【试除法】func Gcd4(a int, b int) int {    //保证第一个数大于等于第二个数    if a < b {        a, b = b, a    }    //试除    for i := b; i >= 2; i-- {        if a%i == 0 && b%i == 0 {            return i        }    }    //试除失败,1就是最大公约数    return 1}//1.两个数的最小公倍数:【利用最大公约数】func Lcm1(a int, b int) int {    return a / Gcd2(a, b) * b}//2.两个数的最小公倍数:【试乘法】func Lcm2(a int, b int) int {    //保证第一个数大于等于第二个数    if a < b {        a, b = b, a    }    //试乘    for i := 1; i < b; i++ {        if i*a%b == 0 {            return i * a        }    }    //试乘失败,两个数的乘积就是最小公倍数    return a * b}//1.n个数的最小公倍数:【遍历法】func LcmN1(s []int) int {    ret := 1    for i := len(s) - 1; i >= 0; i-- {        ret = Lcm1(ret, s[i])    }    return ret}//2.n个数的最小公倍数:【二分法】func LcmN2(s []int) int {    slen := len(s)    if slen == 1 {        return s[0]    } else {        if true {            //并行            ch := make(chan int, 0)            go func() {                ch 

敲 go test -v -test.run TestLcm 命令,结果如下:

ad462e5ab18ebcef9454d7cd73d9c7cf.png

***

[评论](https://user.qzone.qq.com/3182319461/blog/1599866628)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值