zoukankan      html  css  js  c++  java
  • 欧几里得算法实现、正确性证明及时间复杂度分析

    求最大公约数的最常用的算法是欧几里得算法,也称为辗转相除法。
    问题定义为求i和j的最大公约数gcd(i,j),其中i和j是整数,不妨设i>j。
    算法可以递归的表示:

    1.如果j能整除i,那么gcd(i,j)=j;
    2.j不能整除i,令r=i%j,那么gcd(i,j)=gcd(j,r).
    

      上面的算法对于i<j的情况也是可以的,实际上是做了一次交换。


    使用C语言实现:

    int gcd(int i, int j)
    {
        int r = i % j;
        return r == 0 ? j : gcd(j, r);
    } 
    

      


    算法正确性分析

    下面一步一步的切入

    在证明之前先看一个说明:

    对于两个数i=md,j=nd.

    i、j的最大公约数是d的充要条件是:m和n互质。


    再看另一个说明:

    如果m和n互质,那么(m-kn)和n也互质。

    这个可以用反正法:

    假设(m-kn)和n不互质,那么存在一个因子e,使得(m-kn)=en。

    那么m=(k+e)n,这与m、n互质的题目条件违背,所以假设不成立。

    则(m-kn)和n也互质。


    算法的步骤1,显然是成立的,因为这就是最大公约数的定义。

    算法的步骤2:

    其实算法证明的目标是r=i%j != 0时,gcd(i,j)=gcd(j,r)。

    根据已知条件,设d是i、j的最大公约数,则

    i=md,j=nd,其中m、n是互质的。(如果m、n不互质,d就不是最大公约数)

    (现在要找的是gcd(j,r)的最大公约是也是d,那么就要用d去表示r,证明这个表达式的系数和n互质,那么d就是r和j的最大公约数)

    接着上面的说,由于r=i%j,则i=kj+r其中k>=1,k=[m/n],带入上面的等式:

    md=kndr,所以r=(m-kn)d,又因为j=nd,n和(m-kn)互质,所以d是j、r的最大公约数。

    算法的步骤1,显然成立(最大公约数定义).关键是要证明步骤2.
    设d是i和j的最大公约数,
    那么i=md,j=nd,m和n互质(否则d不是最大公约数).
    由r=i%j可以得到i=kj+r,k=⌊m/n⌋,k≥1(我们前面假设过i>j).
    把i=md,j=nd代入得到
    md=knd+r
    那么
    r=(m-kn)d
    m-kn和m也是互质的.
    所以得到d是j和r的最大公约数.
    

     

    时间复杂度分析

    逆着看该算法,最后的余数是0,倒数第二次余数是d,倒数第三次是kd,k>1…
    由于组成了一个数列,{0,d,kd,nkd+d,…}
    数列的n项加上n+1项,比n+2项要小,所以比斐波纳契数列增长的要快.
    我们已知斐波纳契数列增长速度是指数,那么待分析的数列也是指数增长.
    设欧几里得算法需要k次,那么j=O(2^k),则k=O(lg j).
    所以欧几里得算法求最大公约数的时间复杂度是对数量级的,速度非常快.

  • 相关阅读:
    小米智能家居接入智能家居平台homeassistant的方法
    我的nodejs 快速入门
    node.js JS对象和JSON字符串之间的转换
    Mac安装搭建sublimeText3开发Nodejs环境
    使用Xcode IDE写node.js
    nodejs中exports与module.exports的区别
    安装pysqlite2
    linux 终端分屏命令
    MQTT学习笔记
    Cache缓存
  • 原文地址:https://www.cnblogs.com/stemon/p/4720013.html
Copyright © 2011-2022 走看看