• 2.7 编程之美--最大公约数的3种解法[efficient method to solve gcd problem]


    【本文链接】

    http://www.cnblogs.com/hellogiser/p/efficient-method-to-solve-gcd-problem.html

    【题目】

      求两个正整数的最大公约数Greatest Common Divisor (GCD)。如果两个正整数都很大,有什么简单的算法吗?例如,给定两个数1 100 100 210 001, 120 200 021,求出其最大公约数。

    【解法】


     【1. 辗转相除法】

    辗转相除法:f(x,y) = f(y , x % y)(x>y)

    f(42,30) = f(30,12) = f(12,6) = f(6,0) = 6

    【代码】

     C++ Code 
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
     
    /*
        version: 1.0
        author: hellogiser
        blog: http://www.cnblogs.com/hellogiser
        date: 2014/7/8
    */


    int gcd(int x, int y)
    {
        
    if(x < y)
            
    return gcd(y, x);
        
    if(y == 0)
            
    return x;
        
    else
            
    return gcd(y, x % y);
    }

    此方法中用到了取模运算,对于大整数而言,取模运算(其中用到了除法)开销是非常昂贵的,将成为整个算法的瓶颈。


    【2. 辗转相减法】

    辗转相减法:f(x,y) = f(y, x-y) (x>y)

    f(42,30) = f(30,12) = f(12,18) = f(18,12) = f(12,6)=f(6,6)=f(6,0)=6

    【代码】

     C++ Code 
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
     
    /*
        version: 1.0
        author: hellogiser
        blog: http://www.cnblogs.com/hellogiser
        date: 2014/7/8
    */


    int gcd(int x, int y)
    {
        
    if(x < y)
            
    return gcd(y, x);
        
    if(y == 0)
            
    return x;
        
    else
            
    return gcd(y, x - y);
    }

    这个算法免去了大整数除法的繁琐,但同样也有不足之处。最大的瓶颈是迭代的次数过多,如果出现(1 000 000 000,1)这类情况,那就相当让人郁闷了。


    【3. 奇偶法】

    奇偶法:

    此种方法是将解法1)和解法2)结合起来,降低计算复杂度的同时也降低迭代次数。

    1:若 x, y均为偶数,f (x,y) = 2 * f(x / 2, y / 2) = 2 * f(x >> 1, y >> 1)

    2:若x为偶,而y为奇,f (x , y )  = f (x / 2, y) = f ( x >> 1, y)

    3:若x为奇,y为偶,f ( x, y)  = f (x , y / 2) = f(x , y >> 1)

    4:若x,y均为奇,f ( x, y ) = f (y , x - y)

    在f(x, y) = f(y, x - y)之后,(x - y)是一个偶数,下一步一定会有除以2的操作。

    因此最坏情况下时间复杂度为O(log2 (max(x,y)))。

    f (42 , 30 ) = 2 * f (21,15)      

                       = 2 * f (15,6)    

                       = 2 * f (15,3)      

                       = 2 * f (3,12)  =2 * f (12,3)  

                       = 2 * f (6,3)         

                       = 2 * f (3,3)       

                       = 2 * f (3,0)         

                       = 2 * 3

                       = 6

    代码】

     C++ Code 
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
     
    /*
        version: 1.0
        author: hellogiser
        blog: http://www.cnblogs.com/hellogiser
        date: 2014/7/8
    */


    bool IsEven(int x)
    {
        
    return (x & 0x1) == 0;
    }

    int gcd(int x, int y)
    {
        
    if(x < y)
            
    return gcd(y, x);
        
    if(y == 0)
            
    return x;
        
    else
        {
            
    if(IsEven(x))
            {
                
    if(IsEven(y)) //case 1,x,y均为偶数
                    return 2 * gcd(x >> 1, y >> 1);
                
    else  //case 2,x为偶,y为奇
                    return gcd(x >> 1, y);
            }
            
    else
            {
                
    if(IsEven(y)) //case 3,x为奇,y为偶
                    return gcd(x, y >> 1);
                
    else  //case 4,x,y均为奇
                    return gcd(y, x - y);
            }
        }
    }

    【参考】

    http://blog.csdn.net/ajioy/article/details/7478008

    http://blog.csdn.net/rein07/article/details/6739688

    【本文链接】

    http://www.cnblogs.com/hellogiser/p/efficient-method-to-solve-gcd-problem.html

    个人学习笔记,欢迎拍砖!---by hellogiser

    Author: hellogiser
    Warning: 本文版权归作者和博客园共有,欢迎转载,但请保留此段声明,且在文章页面明显位置给出原文连接。Thanks!
    Me: 如果觉得本文对你有帮助的话,那么【推荐】给大家吧,希望今后能够为大家带来更好的技术文章!敬请【关注】
  • 相关阅读:
    访客登录方案设计与应用
    VS Code下载
    dockerfile COPY命令失效
    mysql排序字段值相等时,分页数据重复
    go使用json包Marshal方法得到异常结果[123 125]
    Mysql知识点概览
    dockercompose安装
    docker安装
    Shell脚本执行报错:Syntax error: "(" unexpected
    二进制数的位运算,角色权限,多种账号来源
  • 原文地址:https://www.cnblogs.com/hellogiser/p/efficient-method-to-solve-gcd-problem.html
Copyright © 2020-2023  润新知