当前位置: 首页 > news >正文

算法-最大公约数

最大公约数是一个很经典的数学问题,对于这个问题有四种通用的解法,质因数分解法,短除法,不过比较常用的还是辗转相除法,算法出自于欧几里的著作《几何原本》,还有一个就是出自《九章算术》的更相减损法,一般实现的时候都是通过辗转相除法实现,基本的逻辑是这样的:假设把a和b的最大公约数表示成为f(a,b),并且a>=b>0。现在取k=a/b,m=a%b,则a=k*b+m,变形为m=a - k*b;x和y能被f(a,b)整除,那么m也能被f(a,b)整除,f(a,b) = f(b,a%b)。

循环取值

基于上面的逻辑我们定义两个数字a,b,首先mod=a%b余数,然后将b赋值给a,mod赋值给b,跳出循环返回a就是最大公约数,代码如下:

-(NSInteger)maxDivisor:(NSInteger)a secondNumber:(NSInteger)b{
    if (a<b) {
        a=a+b;
        b=a-b;
        a=a-b;
    }
    while (b!=0) {
        NSInteger  mod=a%b;
        a=b;
        b=mod;
    }
    return a;
}

辗转相除递归版

出于对循环的理解,我们可以通过递归实现:

-(NSInteger)maxmodRecursive:(NSInteger)a secondNumber:(NSInteger)b{
    if (a<b) {
        a=a+b;
        b=a-b;
        a=a-b;
    }
    if (b==0) {
        return a;
    }else{
        return [self maxmodRecursive:b secondNumber:a%b];
    }
}

辗转相除的变形 

辗转相除法对大整数求最大公约数,辗转相除法的效率就出现了瓶颈,对于大整数而言,取模运算(用到除法)的开销非常的昂贵,这是欧几里得算法的局限性,其实我们可以借鉴欧几里得的辗转相除法优化一下。我们需要认识到一个数学知识就是两个数的最大公约数等于较小数和两个数差值之间的公约数。可以通过“-”运算,即 f(a,b)=f(a-b,b)。

-(NSInteger)maxRecursive:(NSInteger)a secondNumber:(NSInteger)b{
    if (a<b) {
        a=a+b;
        b=a-b;
        a=a-b;
    }
    if (b==0) {
        return a;
    }else{
        return [self maxRecursive:b secondNumber:a-b];
    }
}

对于大数运算问题通过以上形式解决了,那就是当a和b相差很多时,算法的迭代次数会过高,导致了算法的效率较低,a=1000,b=1,们要考虑其他的优化。

移位运算

上面的方法对于大整数和迭代的问题没能很好的解决,我们可以通过移位运算很好解决以上的问题:

(1)如果b=k*b1,a=k*a1.那么有f(a,b)=k*f(a1,b1)

(2)如果a=p*a2,p为素数,并且b%p != 0,那么f(a,b) = f(p*a2,b) = f(a2,b)

于是我们得到下面的解决方法:

将p = 2,

若a,b均为偶数,f(a,b) = 2*f(a/2,b/2) = 2*f(a>>1,b>>1);

若a是偶数,b是奇数,f(a,b) = f(a/2,b) = f(a>>1,b);

若a是奇数,b是偶数,f(a,b) = f(a,b/2) = f(a,b>>1);

若a和b均为奇数,f(a,b) = f(b,a-b)。这时a-b一定是偶数,下一步一定会除以2,算法的时间复杂度是O(log2(max(a,b))

-(NSInteger)maxLogic:(NSInteger)a secondNumber:(NSInteger)b{
    if (a<b) {
        a=a+b;
        b=a-b;
        a=a-b;
    }
    if (b==0) {
        return a;
    }else{
        //a是偶数
        if ((a&1)==0) {
            //b是偶数
            if ((b&1)==0) {
                return [self maxLogic:a>>1 secondNumber:b>>1]<<1;
            }else{//b是奇数
                return [self maxLogic:a>>1 secondNumber:b];
            }
        }else{//a是奇数
            //b是偶数
            if ((b&1)==0) {
                return [self maxLogic:a secondNumber:b>>1];
            }else{//b是奇数
                return [self maxLogic:b secondNumber:a-b];
            }
        }
    }
    return 0;
}

 通过移位运算和减法运算,避开了大整数除法,提高了算法的效率,有些东西还是需要经常研究的~

转载于:https://www.cnblogs.com/xiaofeixiang/p/4532679.html

相关文章:

  • Androd开发之广告栏设计
  • nginx+lua+redis(openresty)配置
  • 模拟 2015百度之星资格赛 1003 IP聚合
  • 增值税发票管理解决方案
  • SQL Server利用RowNumber()内置函数与Over关键字实现通用分页存储过程(支持单表或多表结查集分页)...
  • Ubuntu 下 Mysql 新建数据库和用户
  • 运维角度浅谈MySQL数据库优化
  • springmvc常用的组件,注解,跳转
  • Codeforces Round #306 (Div. 2) E. Brackets in Implications 构造
  • ZH奶酪:【数据结构与算法】并查集基础
  • lnmp 在nginx中配置相应的错误页面error_page
  • Android 官方命令深入分析之Android Debug Bridge(adb)
  • 使用cardme读写VCard文件,实现批量导入导出电话簿
  • 使用SQL Server 2008远程链接时SQL数据库不成功的解决方法
  • 做基准测试时tpcc相关注意点
  • 9月CHINA-PUB-OPENDAY技术沙龙——IPHONE
  • 【RocksDB】TransactionDB源码分析
  • es6要点
  • es的写入过程
  • Java知识点总结(JDBC-连接步骤及CRUD)
  • learning koa2.x
  • MySQL的数据类型
  • React 快速上手 - 06 容器组件、展示组件、操作组件
  • Selenium实战教程系列(二)---元素定位
  • windows下如何用phpstorm同步测试服务器
  • 干货 | 以太坊Mist负责人教你建立无服务器应用
  • 技术发展面试
  • 解决iview多表头动态更改列元素发生的错误
  • 那些被忽略的 JavaScript 数组方法细节
  • 实战|智能家居行业移动应用性能分析
  • 栈实现走出迷宫(C++)
  • postgresql行列转换函数
  • 整理一些计算机基础知识!
  • #我与Java虚拟机的故事#连载13:有这本书就够了
  • (ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY)讲解
  • (附源码)springboot 校园学生兼职系统 毕业设计 742122
  • (理论篇)httpmoudle和httphandler一览
  • (十三)Java springcloud B2B2C o2o多用户商城 springcloud架构 - SSO单点登录之OAuth2.0 根据token获取用户信息(4)...
  • (一)WLAN定义和基本架构转
  • (转)c++ std::pair 与 std::make
  • **登录+JWT+异常处理+拦截器+ThreadLocal-开发思想与代码实现**
  • .NET Core 中的路径问题
  • .net 反编译_.net反编译的相关问题
  • .NET 将混合了多个不同平台(Windows Mac Linux)的文件 目录的路径格式化成同一个平台下的路径
  • .NET牛人应该知道些什么(2):中级.NET开发人员
  • @ComponentScan比较
  • @converter 只能用mysql吗_python-MySQLConverter对象没有mysql-connector属性’...
  • [ C++ ] STL_list 使用及其模拟实现
  • [ C++ ] STL_vector -- 迭代器失效问题
  • [APIO2012] 派遣 dispatching
  • [BZOJ 4598][Sdoi2016]模式字符串
  • [BZOJ3223]文艺平衡树
  • [C#]扩展方法
  • [CTF]php is_numeric绕过
  • [Django 0-1] Core.Email 模块