递归 - 时间复杂度

在本文中, 我们主要介绍如何分析递归算法程序中的时间复杂度。.
在一个递归程序中, 它的时间复杂度 O(T) 一般来说就是他总共递归调用的次数 (定义为 R) 以及每次调用时所花费的耗时 (定义为 O(s)) ,这样我们就可以得出:
(T) = R * O(T) = R∗O(s)
下面让我们来看几个栗子:
 

线性的栗子


正如之前的问题 printReverse所描述的, 需要把一个字串逆序输出. 其中一种递归的解法如下所示:
printReverse(str) = printReverse(str[1...n]) + print(str[0])
其中 str[1...n] 是输入的字串 str 去除了首字母str[0]的切分子串, .
显而易见,这个算法会连续调用 n 次, 这个 n 也就该输入字串的长度. 在每次递归的最后, 我们只打印首字母, 因此该算法每次调用递归所耗费的时间为常量, 即为 {\mathcal{O}(1)}O(1).
把次数和每次耗时进行合计,该递归程序 printReverse(str) 的耗时即为 (printReverse) = n * O(1) = O(printReverse)=n∗O(1)=O(n).
 

执行树


对于递归函数, 像上面的线性化递归调用的栗子其实是很少的,更多的是非线性的. 例如, 之前章节我们讨论的 Fibonacci number ,它的递归关系就定义为更复杂的 f(n) = f(n-1) + f(n-2). 乍看之下, 很难一下子去计算出斐波那契函数的递归调用次数 -_-.
在这个例子里, 我们最好使用 execution tree 这个工具可以用来直观地表示递归程序的执行流. 树中的每一个节点都表示每次对应的递归程序调用. 因此,树中的节点总数与整个递归过程调用的总数相对应。
递归函数的执行树会形成一个 n-ary tree, 其中n 就是这个程序执行下来递归调用的次数. 例如, 斐波那契函数的执行流就是一个二叉树, 如下图所示就是计算 f(4) 的流程树:
 
在一个 n 层的满二叉树, 所有节点数总和应该是 
2^n - 1
 
 
. 因此, 对于递归程序 f(n) 总调用次数的上限也应该是 
{2^n -1}
 
. 所以, 我们得出了递归程序 f(n) 的时间复杂度即为 
{\mathcal{O}(2^n)}
 
 

记忆化


在前面的章节中, 我们讨论过用来优化递归算法时间复杂度的记忆化方法. 通过存储和重复使用中间变量, 记忆化能够极大地降低递归程序的调用次数, 换个说法就是减少执行树中的递归调用分支. 在分析试用了记忆化的递归调用程序的时间复杂度时,千万要记得考虑这种(分支减少的)情况。.
让我们重新再回看前面斐波那契额数列的栗子. 使用记忆化方法的话,我们每次都将斐波那契额数列在 n.节点下的存储, 于是我们可以确保对于每个节点计算需要的递归调用只需要一次. 而且我们知道斐波那契额数列的递归关系是每个 f(n) 都依赖前一个 n-1 的结果. 最终使得计算 f(n) 只调用 n-1 次 之前已经计算好的结果即可. 
现在, 我们可以很轻易的通过前面介绍的公式 O(1)∗n=O(n) .来计算斐波那契额数列函数的时间复杂度。记忆化不仅仅优化算法的时间复杂度,同样也简化了对于时间复杂度的计算。
在下一篇文章中, 我们将讨论如何估算递归程序的空间复杂度.
 
 
 
 原文地址:https://leetcode.com/explore/learn/card/recursion-i/256/complexity-analysis/1669/
 
 
 

LeetCode 递归(Recursion) 培训专题 讲解文章翻译 (附链接)的更多相关文章

  1. LeetCode递归 -2(Recursion) 培训专题 讲解文章翻译 (附链接) (2019-04-09 15:50)

    递归 - 空间复杂度  在本文中, 我们将讨论如何分析递归算法的空间复杂度. 在计算递归算法的空间复杂度时,最需要考虑的两个部分就是: 递归相关空间 (recursion related space) ...

  2. Activity Process Task Application 专题讲解

    Activity Process Task Application 专题讲解 Activity.和进程 为了阅读方便,将文档转成pdf http://files.cnblogs.com/franksu ...

  3. Leetcode之回溯法专题-216. 组合总和 III(Combination Sum III)

    Leetcode之回溯法专题-216. 组合总和 III(Combination Sum III) 同类题目: Leetcode之回溯法专题-39. 组合总数(Combination Sum) Lee ...

  4. 算法与数据结构基础 - 递归(Recursion)

    递归基础 递归(Recursion)是常见常用的算法,是DFS.分治法.回溯.二叉树遍历等方法的基础,典型的应用递归的问题有求阶乘.汉诺塔.斐波那契数列等,可视化过程. 应用递归算法一般分三步,一是定 ...

  5. Atitit  循环(loop), 递归(recursion), 遍历(traversal), 迭代(iterate).

    Atitit  循环(loop), 递归(recursion), 遍历(traversal), 迭代(iterate). 1.1. 循环算是最基础的概念, 凡是重复执行一段代码, 都可以称之为循环. ...

  6. 循环(loop), 递归(recursion), 遍历(traversal), 迭代(iterate)的区别

    表示“重复”这个含义的词有很多, 比如循环(loop), 递归(recursion), 遍历(traversal), 迭代(iterate). 循环算是最基础的概念, 凡是重复执行一段代码, 都可以称 ...

  7. 003_循环(loop), 递归(recursion), 遍历(traversal), 迭代(iterate)的区别

    表示“重复”这个含义的词有很多, 比如循环(loop), 递归(recursion), 遍历(traversal), 迭代(iterate). 循环算是最基础的概念, 凡是重复执行一段代码, 都可以称 ...

  8. Leetcode之分治法专题-169. 求众数(Majority Element)

    Leetcode之分治法专题-169. 求众数(Majority Element) 给定一个大小为 n 的数组,找到其中的众数.众数是指在数组中出现次数大于 ⌊ n/2 ⌋ 的元素. 你可以假设数组是 ...

  9. Leetcode之回溯法专题-212. 单词搜索 II(Word Search II)

    Leetcode之回溯法专题-212. 单词搜索 II(Word Search II) 给定一个二维网格 board 和一个字典中的单词列表 words,找出所有同时在二维网格和字典中出现的单词. 单 ...

随机推荐

  1. SpringBoot定时任务(Spring Schedule )实现方法

    FastDateFormat fdf = FastDateFormat.getInstance("yyyy-MM-dd HH:mm:ss"); fdf.format(new Dat ...

  2. OpenGL ES2.0编程三步曲 -转

    原地址:http://blog.csdn.net/myarrow/article/details/7707943 1. 保存全局变量的数据结构 以下例子程序均基于Linux平台. typedef st ...

  3. 腾讯云linux服务器分区方案

    刚刚在腾讯云买了一台服务器,刚买的服务器的数据盘都是需要自己来分区的,下面就记录一下操作. 通过命令fdisk-l查看硬盘信息 可以看到有两块硬盘/dev/vda和/dev/vdb,启动vda是系统盘 ...

  4. Spark(一)-- Standalone HA的部署

    首先交代一下集群的规模和配置 集群有六台机器,均是VM虚拟机,每台256M的内存(原谅楼主物理机硬件不太给力) 主机名分别是cloud1~cloud6 每台机器上都装有jdk6,和hadoop-2.2 ...

  5. Implementing DDD Reading - Strategic Design

    1. 概念篇 1.1 领域 广义上讲,领域即是一个组织所做的事情以及其中所包含的一切,也是组织的业务范围以及在其中所进行的活动.软件所讨论的领域即是这个组织的领域,应该是清晰明确的.不同的层面或粒度, ...

  6. Android TextView 常见问题与使用总结

    一.文字显示行数设置 1. 仅显示一行文字 android:singleLine="true" setTransformationMethod(TransformationMeth ...

  7. jbpm4(参数设置)

    1.processDefinition.getDescription() <process name="task_test_2" xmlns="http://jbp ...

  8. 使用UnityVS1.8.2搭配VS2013进行Unity3D代码调试(下载+安装+使用+问题解决)

    http://blog.dou.li/UnityVS1_8_2-VS2013.html 备整合UnityVS1.8.2和VS2013调试Unity3D代码,安装后会有些问题无法调试,详情继续往下看. ...

  9. ACE消息队列(转)

    1    消息队列 ACE消息队列由三个部分组成:消息队列(ACE_Message_Queue).消息块(ACE_Message_Block).数据块(ACE_Data_Block) 1.1    A ...

  10. 说说C#的数学类,Math,浮点数(上)

    说说C#的数学类,Math,浮点数 C#语言支持下图所看到的的数值类型,各自是整数,浮点数和小数 可能不是非常清楚,可是细致看看还是能看清楚的. 在一个C#程序中,整数(没有小数点的数)被觉得是一个i ...