递归树

递归的思想就是,将大问题分解为小问题来求解,然后再将小问题分解为小小问题。

这样一层一层地分解,直到问题的数据规模被分解得足够小,不用继续递归分解为止。

如果我们把这个一层一层的分解过程画成图,它其实就是一棵树。我们给这棵树起一个名字,叫作递归树。

递归代码的时间复杂度分析起来很麻烦,可以利用递推公式来求解算法的时间复杂度,如求解归并排序、快速排序的时间复杂度

但是些情况,比如快排的平均时间复杂度的分析,用递推公式的话,会涉及非常复杂的数学推导。

此时我们就可以借助递归树来分析递归实现算法的时间复杂度

如何用递归树求解时间复杂度

递归树分析归并排序时间复杂度

归并排序每次会将数据一分为二,因为每次分解都是一分为二,所以代价很低,我们把时间上的消耗记作常量 1。

归并算法中比较耗时的是归并操作,也就是把两个子数组合并为大数组。

每一层归并操作消耗的时间总和是一样的,跟要排序的数据规模有关。把每一层归并操作消耗的时间记作 n。

那么只需要知道这棵树的高度 h,用高度 h 乘以每一层的时间消耗 n,就可以得到总的时间复杂度 O(n∗h)。

从归并排序的原理可以看出来,归并排序的递归树是一棵满二叉树,而满二叉树的高度大约是log n 。

所以,归并排序递归实现的时间复杂度就是 O(nlogn)。

当然,除了用递归树来分析归并排序递归实现的时间复杂度,还可以利用递推公式来分析

具体方法在我的归并排序分析里面有:https://blog.csdn.net/qq_42006733/article/details/104415767

递归树分析快速排序时间复杂度

关于利用递推公式来分析递归实现算法的时间复杂度对于快速排序来说就相对于复杂。

快速排序在最好情况下,分区点选择及其合理,每次分区都能一分为二的时候。

这个时候用递推公式 T(n)=2T(n/2​)+n,很容易就能推导出时间复杂度是 O(nlogn)。

但是,并不可能每次分区都这么幸运,正好一分为二。

假设平均情况下,每次分区之后,两个分区的大小比例为 1:k。

当 k=9 时,如果用递推公式的方法来求解时间复杂度的话,递推公式就写成 T(n)=T(n/10​)+T(9*n/10​)+n。

利用递推公式来分析时间复杂度也是可以的,但是推导过程就很复杂。

在这种情况下利用递归树就简单的很多。

仍假设k=9 的时候,快速排序的过程中,每次分区都要遍历待分区区间的所有数据 。

跟归并排序一样,每一层分区操作所遍历的数据的个数之和就是 n。

我们现在只要求出递归树的高度 h,这个快排过程遍历的数据个数就是 h∗n ,也就是说,时间复杂度就是 O(h∗n)。

但是归并排序中每次分区都是一分为二,所以归并排序的递归树是满二叉树。高度为log n

而快速排序每次分区并不是均匀地一分为二,所以递归树并不是满二叉树。高度就不是log n 了。

归并排序中,开始合并的条件是数据已经被划分为单个的了,而快速排序结束的条件就是待排序的小区间,大小为 1。

那么就是说叶子节点里的数据规模是 1。而根节点是n。

那么递归树中最短的一个路径每次都乘以 1/10​,最长的一个路径每次都乘以 9/10 ​。

遍历数据的个数总和就介于 nlog10​n 和 nlog910​​n 之间。

根据复杂度的大 O 表示法,对数复杂度的底数不管是多少,我们统一写成 log n

当分区大小比例是 1:9 时,快速排序的时间复杂度仍然是 O(nlogn)。

若k = 99,也就是说每次的分区更加不平均了,还是类似的方法,求的树的最短路径就是 log100​ n,最长路径是 log 99/100 ​​n

只是底数变了,但是时间复杂度也仍然是 O(nlogn)。

不管k的值是多少,甚至是 999,9999,只要 k 的值不随 n 变化,是一个事先确定的常量,那快排的时间复杂度就是 O(nlogn)。

所以说快排的平均时间复杂度就是 O(nlogn)。

递归树分析斐波那契数列时间复杂度

斐波那契数列就是经典的递推,F(1)=1,F(2)=1, F(n)=F(n - 1)+F(n - 2)(≥ 3,∈ N*)

用代码表示就是

int f(int n) {if (n == 1) return 1;if (n == 2) return 2;return f(n-1) + f(n-2);
}

同样的方法,f(n) 分解为 f(n−1) 和 f(n−2),每次数据规模都是 −1 或者 −2,叶子节点的数据规模是 1 或者 2。

根节点走到叶子节点,每条路径是长短不一的。

如果每次都是 −1,那最长路径大约就是 n;如果每次都是 −2,那最短路径大约就是 n/2。

斐波那契数列分解后的合并只是一次加法运算,若把这次加法运算的时间消耗记作 1。

从上往下,第一层的总时间消耗是 1,第二层的总时间消耗是 2,第三层的总时间消耗就是 22。

依次类推,第 k 层的时间消耗就是 2^k−1

如果路径长度都为 n,那这个总和就是 2^n−1。

如果路径长度都是 2n​ ,那整个算法的总的时间消耗就是 2^(n/2)​−1。

所以斐波那契数列算法的时间复杂度就介于 O(2^n) 和 O(2^(n/2)​) 之间。

虽然这样得到的结果只是一个范围,但是已经可以明确这个算法的时间复杂度是指数级的,非常之高。

递归树——分析递归算法的时间复杂度相关推荐

  1. 递归树求解递归算法的时间复杂度

    递归算法时间复杂度的计算方程式一个递归方程: 在引入递归树之前可以考虑一个例子: T(n) = 2T(n/2) + n2 迭代2次可以得: T(n) = n2 + 2(2T(n/4) + (n/2)  ...

  2. 算法:递归(借助递归树来求解分析递归算法的时间复杂度)

    递归代码的时间复杂度分析起来非常麻烦,今天我们尝试来借助递归树分析递归算法的时间复杂度. 1. 递归树与时间复杂度分析 递归的思想就是将大问题一层一层地分解为小问题来求解,如果我们把这个分解过程画成图 ...

  3. 基于主定理以及递推树求解递归算法的时间复杂度

    非递归算法的时间复杂度可以通过找到执行次数最多的代码,计算其执行次数即可.但是递归算法的时间复杂度则无法通过这种方式求得.有一种最简单的求递归算法的方式,即利用递推方法求解时间复杂度.如下所示: 这种 ...

  4. 用递归树求解递归算法时间复杂度

    文章内容.图片均来自极客时间. 递归代码复杂度分析起来比较麻烦.一般来说有两种分析方法:递推公式和递归树. 1 递推公式法 归并排序的递推公式是: merge_sort(p-r) = merge(me ...

  5. 递归树-分析时间复杂度

    递归的思想就是把一个大问题分解为小问题,再把小问题继续分解下去,一直到无法再分为止.所以递归的核心思路就是找到递归公式和终止条件.那么什么是递归树?简单来说,这颗树是由递归的子问题组成树,树的节点就是 ...

  6. 递归树分析时间复杂度

    递归树分析时间复杂度 递归的思想就是,将大问题分解为小问题来求解,然后再将小问题分为小小问题.直到问题的数据规模分解的足够小,不用继续递归分解为止 方法: 1.知道树的高度h,用高度h乘以每一层的时间 ...

  7. [数据结构]递归树:借助树求解递归算法的时间复杂度

    文章目录 递归树与时间复杂度分析 实战一:分析快速排序的时间复杂度 实战二:分析斐波那契数列的时间复杂度 实战三:待补充,先学其他的... 递归树与时间复杂度分析 我们前面讲过,递归的思想就是,将大问 ...

  8. 递归树求递归算法时间复杂度

    开篇前言:为什么写这篇文章?笔者目前在学习各种各样的算法,在这个过程中,频繁地碰到到递归思想和分治思想,惊讶于这两种的思想的伟大与奇妙的同时,经常要面对的一个问题就是,对于一个给定的递归算法或者用分治 ...

  9. 递归树: 如何借助树来求解递归算法的时间复杂度

    ------ 本文是学习算法的笔记,<数据结构与算法之美>,极客时间的课程 ------ 今天,来讲树这种数据结构的一种特殊的应用,递归树. 我们都知道,递归代码的时间复杂度分析起来很麻烦 ...

最新文章

  1. css毛玻璃效果白边_CSS3毛玻璃效果(blur)有白边问题的解决方法
  2. Kali Linux常用服务配置教程安装及配置DHCP服务
  3. Linux tcp同时多个连接,Linux下网络编程(2)——TCP多连接,1个server,多个client...
  4. PAT甲级1061 Dating:[C++题解]字符串处理(C语言格式控制牛逼!)
  5. input-text
  6. 1.深度学习练习:Python Basics with Numpy(选修)
  7. 大数据学习笔记:创建与配置虚拟机[Ubuntu + CentOS]
  8. jmeter 配置 slave 代理压测机
  9. 跨浏览器javascript
  10. 《机器学习》瓜书—周志华
  11. 微信小程序data-xx 的使用
  12. macbook或mac Apple ID 更新提示连接服务器出错
  13. 关于浏览器的几个高度和宽度
  14. c语言 符号自动换行,单片机串口发送字符为什么会自动换行?
  15. 基于Python3(Autosub)以及Ffmpeg配合GoogleTranslation(谷歌翻译)为你的影片实现双语版字幕(逐字稿)
  16. 工程伦理2021年春季学期线上课程习题全部解答
  17. 堆排序的基本概念和基本思路
  18. Shell脚本(一)
  19. wireshark简易抓包分析——ping指定大小包长多28Byte
  20. 机器学习之朴素贝叶斯算法原理+Python实现

热门文章

  1. Android自定义组件系列【16】——最帅气的自动滚动广告条
  2. RUI topic 6
  3. 推荐系统中物品相似度计算
  4. 46 使用构造函数创建对象
  5. 修改注册表解决Win10 SSD卡顿
  6. 这是一份数据库酒店管理的代码【简易版】
  7. PerformanceCounter详解,使用方法
  8. 华院计算|维托里斯—最长寿的数学家
  9. git 将dev分支合并到master主干
  10. 获得店铺详情 API 返回值说明