python递归算法的时间复杂度分析_【转】递归算法的时间复杂度计算

开篇前言:为什么写这篇文章?笔者目前在学习各种各样的算法,在这个过程中,频繁地碰到到递归思想和分治思想,惊讶于这两种的思想的伟大与奇妙的同时,经常要面对的一个问题就是,对于一个给定的递归算法或者用分治思想缩小问题规模的算法,如何求解这个算法的时间复杂度呢?在google过很多的博文后,感觉这些博文总结的方法,有很好优秀的地方,但是都不够全面,有感于此,笔者决定总结各家之长,作此博文,总结各种方法于此,有不足之处,欢迎各位批评指证!

在算法的分析中,当一个算法中包含递归调用时,其时间复杂度的分析会转化成为一个递归方程的求解。而对递归方程的求解,方法多种多样,不一而足。本文主要介绍目前主流的方法:代入法,迭代法,公式法,母函数法,差分方程法。

【代入法】代入法首先要对这个问题的时间复杂度做出预测,然后将预测带入原来的递归方程,如果没有出现矛盾,则是可能的解,最后用数学归纳法证明。

【举   例】我们有如下的递归问题:T(n)=4T(n/2)+O(n),我们首先预测时间复杂度为O(n2),不妨设T(n)=kn2(其中k为常数),将该结果带入方程中可得:左=kn2,右=4k(n/2)2+O(n)=kn2+O(n),由于n2的阶高于n的阶,因而左右两边是相等的,接下来用数学归纳法进行验证即可。

【迭代法】迭代法就是迭代的展开方程的右边,直到没有可以迭代的项为止,这时通过对右边的和进行估算来估计方程的解。比较适用于分治问题的求解,为方便讨论起见,给出其递归方程的一般形式:

【举   例】下面我们以一个简单的例子来说明:T(n)=2T(n/2)+n2,迭代过程如下:

容易知道,直到n/2^(i+1)=1时,递归过程结束,这时我们计算如下:

到这里我们知道该算法的时间复杂度为O(n2),上面的计算中,我们可以直接使用无穷等比数列的公式,不用考虑项数i的约束,实际上这两种方法计算的结果是完全等价的,有兴趣的同学可以自行验证。

【公式法】这个方法针对形如:T(n) = aT(n/b) + f(n)的递归方程。这种递归方程是分治法的时间复杂性所满足的递归关系,即一个规模为n的问题被分成规模均为n/b的a个子问题,递归地求解这a个子问题,然后通过对这a个子问题的解的综合,得到原问题的解。这种方法是对于分治问题最好的解法,我们先给出如下的公式:

公式记忆:我们实际上是比较n^logba和f(n)的阶,如果他们不等,那么T(n)取他们中的较大者,如果他们的阶相等,那么我们就将他们的任意一个乘以logn就可以了。按照这个公式,我们可以计算【迭代法】中提到的例子:O(f(n))=O(n2),容易计算另外一个的阶是O(n),他们不等,所以取较大的阶O(n2)。太简单了,不是吗?

需要注意:上面的公式并不包含所有的情况,比如第一种和第二种情况之间并不包含下面这种情况:f(n)是小于前者,但是并不是多项式的小于前者。同样后两种的情况也并不包含所有的情况。为了好理解与运用的情况下,笔者将公式表述成如上的情况,但是并不是很严谨,关于该公式的严密讨论,请看这里。但是公式的不包含的情况,我们很少很少碰到,上面的公式适用范围很广泛的。

特别地,对于我们经常碰到的,当f(n)=0时,我们有:

【母函数法】母函数是用于对应于一个无穷序列的幂级数。这里我们解决的递归问题是形如:T(n)=c1T(n-1)+c2T(n-2)+c3T(n-3)+...+ckT(n-k)+f(n)。为说明问题简便起见,我们选择斐波那契数列的时间复杂度作为例子进行讨论。

【举  例】斐波那契数列递归公式:T(n)=T(n-1)+T(n-2)。这里我们假设F(n)为第n项的运算量。则容易得到:F(n)=F(n-1)+F(n-2),其中F(1)=F(2)=1.我们构造如下的母函数:G(x)=F(1)x+F(2)x2+F(3)x3+......,我们可以推导如下:

上面的方法计算相对来说是比较简单的,关键在于对于母函数的理解,刚开始的时候可能不是很好理解,对于母函数可以参考这里和维基百科这里。

【差分方程法】可以将某些递归方程看成差分方程,通过解差分方程的方法来解递归方程,然后对解作出渐近阶估计。这里我们只考虑最长常见的递归形式,形如:T(n)=c1T(n-1)+c2T(n-2)+c3T(n-3)+...+ckT(n-k)+f(n),其中c1,c2,...ck为常数且不等于0;我们对该方程的求解如下:

对应上面的齐次方程的特征方程为:

如果解得t=r是该特征方程的m重根,则这m个解的形式为:{rnn*rnn2rn...    nm-1rn},其余的关于复数解的形式和普通的线性方程组的形式类似,不再赘述。接下来,我们要求解该方程的对应非齐次方程组的通解,这里我们针对该方程的特殊形式,不加证明地给出如下的通解形式:

则和线性代数中的解一样,原方程的解等于齐次方程组的通解+特解,即:

最后由初始条件确定a(i)的值即可。

为了帮助理解,我们举两个例子看看,就明白是怎么回事了。

【举 例1】递归方程如下:

(1)写出对应齐次方程的特征方程:

得到基础解系为:{t1n,  t2n}

(2)计算特解,对于本题,直接观察得特解为:-8

(3)得到原方程解的形式为:T(n)=a0t1n+a1t2n-8

(4)代入n=0,n=1的情况,得到a0,a1,最后可得:

可以看到该方程形式和上面讨论过的斐波那契数列只差一个常数8,因而两者的时间复杂度是相同的。有兴趣的同学可以按照这个方法再次计算斐波那契数列的时间复杂度验证一下。

【举  例2】递归方程如下:

(1)计算对应齐次方程的基础解析:

特征方程为:C(t)=t^2-4t-4=0,得到一个2重根t=2.因而其基础解为:{2n      n*2n}

(2)由于f(n)=n*2n,对应上面表格的最后一种情况,得到特解形式为:T(n)=n2(p0+p1n)2n代入原递归方程可得:p0=1/2,p1=1/6

(3)原方程解的形式为:T(n)=a0*2n+a1*n*2n+n2(1/2+n/6)2n,代入T(0),T(1)得:a0=a1=0

(4)综上:T(n)=n2(1/2+n/6)2n

因而时间复杂度为:O(n32n)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/500839.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

php员工积分绩效,详解绩效积分奖励制

制度设计绩效积分奖励制度建立在企业科学有效的绩效考核的基础上,对员工绩效实行积分,绩效积分形成“福利购买力”,在购买力达到一定水平后,员工可以凭借获得的购买力获取企业提供的弹性福利。企业通过绩效考核对员工进行杰出、优…

rhel系统启动过程_Linux系统启动过程分析

[原创]Linux系统启动过程分析-wjlkoorey258-ChinaUnix博客http://blog.chinaunix.net/uid-23069658-id-3142047.html经过对Linux系统有了一定了解和熟悉后,想对其更深层次的东西做进一步探究。这当中就包括系统的启动流程、文件系统的组成结构、基于动态库和静态库的…

php连接数据库非明文,MySQL 数据库配置 SSL 安全连接

当使用非加密方式连接MySQL数据库时,在网络中传输的所有信息都是明文的,可以被网络中所有人截取,敏感信息可能被泄露。在传送敏感信息(如密码)时,可以采用SSL连接的方式。配置MySQL服务端支持SSL连接,MySQL 5.7.6以前版…

php设置路径别名,react设置文件路径别名的具体方法你知道么

文章环境:“react”: “^16.13.1” 版本react官方脚手架默认是将webpack配置隐藏起来了,在进行配置之前需要将webpack给暴露出来。1、输入命令 npm run eject会出现一个命令提示:这是一个单向操作,确认操作后不可逆转/返回?输入 …

vue接收json数据_Vue之使用ajax获取json数据,并用v-for循环显示在表格中

运行的时候,出现了php跨域问题,解决办法是在php的头文件中添加了如下代码:header(Content-Type: application/json);header(Content-Type: text/html;charsetutf-8);header(Access-Control-Allow-Origin:*);header(Access-Control-Allow-Meth…

oracle告警日志备份,教你怎样用Oracle方便地查看报警日志错误

在网上查了几天的资料,尝试综合清除告警日志内容及建外部表的方式来解决这一问题。一:备份并清除告警日志内容将每天的告警日志备份好,然后进行清除。1:备份报警日志在$ORACLE_HOME/SID/bdump/ 目录下,按日期备份alert_ORACLE_你…

iview table 自定义列_基于VueJS的render渲染函数打造一款非常强大的IView 的Table组件...

1、render渲染函数的介绍字符串模板的代替方案,允许你发挥 JavaScript 最大的编程能力。该渲染函数接收一个 createElement 方法作为第一个参数用来创建 VNode。如果组件是一个函数组件,渲染函数还会接收一个额外的 context 参数,为没有实例的…

oracle中主键创建的语法,Oracle中主键、外键、索引、序列、唯一性约束的创建

1、主键的创建方法一:直接在sql语句中声明字段主键约束create table table_name (id type[length] constraint pk_name primary key,name tyoe[length],age type[length],class_id);方法二:alter更改表添加约束alter table table_name add constraint pk…

python的email模块_python email 模块

import smtplibimport osfrom email.mime.text import MIMETextfrom email.mime.multipart import MIMEMultipartimport tracebackimport timedef send(self,contentNone):发送邮件server Noneindex 1 #邮件重试while index < 3:index 1try:server smtplib.SMTP_SSL(&qu…

oracle查被锁存储过程,oracle 结束被锁的包或存储过程

问题现象&#xff1a;在pl/sql编译包或者是存储过程procedure等&#xff0c;编译一直未响应。问题原因&#xff1a;ORACLE 存储过程或包被锁&#xff0c;编译不了问题解决方法&#xff1a;第一步&#xff1a;查找存储过程被哪些session锁住而无法编译select * FROM dba_ddl_loc…

redis aof 备份和恢复_Redis 持久化机制的介绍,了解这些流程很重要

我们已经知道对于一个企业级的redis架构来说&#xff0c;持久化是不可减少的。企业级redis集群架构&#xff1a;海量数据、高并发、高可用持久化主要是做灾难恢复&#xff0c;数据恢复&#xff0c;也可以归类到高可用的一个环节里面去&#xff0c;比如你redis整个挂了&#xff…

oracle 作业已存在,ORA-31634: 作业已存在

服务器上数据泵定时备份任务失败&#xff0c;查看日志报错如下&#xff1a;[oraclehs02 log]$ more expdp_bi_2019-11-02.logExport: Release 11.2.0.4.0 - Production on 星期六 11月 2 00:00:03 2019Copyright (c) 1982, 2011, Oracle and/or its affiliates. All rights res…

最近公共祖先_leetcode No.236 二叉树的最近公共祖先

承接二叉搜索树的最近公共祖先。题目链接&#xff1a;二叉树的最近公共祖先 - 力扣&#xff08;LeetCode&#xff09;​leetcode-cn.com题目描述&#xff1a;给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。百度百科中最近公共祖先的定义为&#xff1a;“对于有根树 T…

python methodtype_Python的实例定属性和方法或类绑定方法

一、给实例对象绑定属性和方法&#xff1a;1、给实例绑定属性&#xff1a;先定义一个Student类#!/usr/bin/pythonclass Student(object):pass然后绑定属性&#xff1a;s Student()s.name AAA # 动态给实例绑定一个属性print(s.name)#输出AAA2、给实例绑定方法&#xff1a;先定…

oracle 时间间隔,ORACLE JOB间隔时间参考

关键字: oracle job 间隔时间 trunc假设你的存储过程名为PROC_RAIN_JM再写一个存储过程名为PROC_JOB_RAIN_JM内容是&#xff1a;Create Or Replace Procedure PROC_JOB_RAIN_JM Is li_jobno Number; Begin DBMS_JOB.SUBMIT(li_jobno,PROC_RAIN_JM;,SYSDATE,TRU…

canvas画布会黑屏吗_Android SurfaceView 黑屏问题

说一个真实的案例。其中需求要做一个绘图功能&#xff0c;一听到绘图&#xff0c;自然而然就像到了SurfaceView这个类。所以我就用了。android:layout_width"match_parent"android:layout_height"match_parent"android:orientation"vertical" &g…

oracle连续周数,详细讲解Oracle数据库的“周数计算”

详细讲解Oracle数据库的“周数计算”以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;——日期计算 算第n周的第一天及最后一天是几号 by keynes—— ww的算法为每年 月 日为第一周开始 date …

probe request帧结构_WLAN 无线网络 09 - 管理帧

0000&#xff0c;Association request&#xff1a;关联请求帧认证成功后&#xff0c;STA就会进入关联阶段&#xff0c; 这个交互的目的是为了加入这个BSS 并获取一个AID。通过Association Request携带的信息&#xff0c;使AP了解STA的相关能力信息&#xff0c;这样 AP就可以决定…

oracle 31640,导数据时ora-31640报错

单实例数据库10.2.0.4&#xff0c;目标数据库11.2.0.3 rac&#xff0c;目标准备将单实例上的数据导入到rac数据库。在导入过程中报错如下&#xff1a;Processing object type SCHEMA_EXPORT/TABLE/TABLE_DATA. . imported "LBSBUS"."T_MSG_SEND_DETAIL" …

oracle rman备份spfile,RMAN备份恢复之SPFILE的恢复(一)

缺少初始化文件&#xff0c;数据库是无法启动的。如果通过RMAN备份了初始化参数&#xff0c;那么可以通过RMAN对初始化参数进行恢复。这篇文章简单介绍CATALOG方式下初始化参数的恢复问题。初始化参数的丢失和损坏&#xff0c;并不会造成太严重的问题&#xff0c;即使是最坏的情…