一.复杂度分析:

可以理解为递归的深度就是空间复杂度,时间复杂度就是O(T*depth),其中T是每个递归函数的时间复杂度,depth是递归深度.


#空间复杂度O(1)
def sum1_(n):res = 0for i in range(n+1):res+=ireturn res#递归 空间复杂度O(n)
def sum2_(n):if n == 0:return 0return n+sum2_(n-1)res1 = sum1_(n=10)
res2 = sum2_(n=10)
print('==res1:', res1)
print('==res2:', res2)

上式时间复杂度也为O(1*n)=O(n)

二.例子

1.计算x^n:


def pow(x, n):if n==0:return 1.t = pow(x, n//2)if n%2:return x*t*telse:return t*tres = pow(2,3)
print('res:', res)

递归深度:logn ,每个递归函数的时间复杂度为O(1),故时间复杂度为O(logn).

空间复杂度:logn

2.假如这里有 n 个台阶,每次你可以跨 1 个台阶或者 2 个t台阶,请问n个台阶有多少种走法?

第一步走了一个台阶或第一步走了两个台阶,到下一个台阶也是类似,故这是一个递归。

n个台阶就是,走了一个台阶后加剩下n-1台阶的走法,走了两个台阶后剩下n-2台阶的走法,

f(n)=f(n-1)+f(n-2)

终止条件:只剩一个台阶一种走法,只剩两个台阶两种走法,

f(1)=1,f(2)=2

def fun(n):if(n == 1): return 1elif (n == 2): return 2else:return fun(n - 1) + fun(n - 2)

每个递归函数的时间复杂度为O(1),空间复杂度:O(2^n), 故时间复杂度为O(2^n).

缺点:堆栈溢出、重复计算、函数调用耗时多、空间复杂度高等

防止递归造成堆栈溢出,加入深度,大于1000就不再溢出

depth=0
def fun(n):global depthdepth+=1print('depth=',depth)if (depth>1000): return -1if(n == 1): return 1elif (n == 2): return 2else:return fun(n - 1) + fun(n - 2)
print(fun(3))

存在大量重复计算:

优化思路1: 

递推,从下到上:

class Solution:def numWays(self, n: int) -> int:a,b=1,1for i in range(n):a,b = a+b,areturn b

思路2,将计算过的值存储在进行判断:


def fun(n,arr):if(n == 1): return 1elif (n == 2): return 2else:if arr[n]!=-1:return arr[n]else:arr[n] = fun(n - 1,arr) + fun(n - 2,arr)return arr[n]
n = 6
arr = [-1]*(n+1)
res= fun(n=n, arr=arr)
print('==res:', res)

3.递归实现全排列:

def swap(a, p, i):a[p], a[i] = a[i], a[p]return a#取第一个数,剩下的做排序,边界条件是开始索引p==终止索引q
def main(a, p, q):res = []def permute(a, p, q):if p == q:res.append(a.copy())print('res:', res)else:for i in range(p, q, 1):swap(a, p, i)permute(a, p+1, q)print('a:', a.copy())swap(a, p, i)#a还原成原顺序,比如2开头的结束了是2 1 3 需要还原成1 2 3 在吧3放在开头在排序print('==a:', a.copy())permute(a, p, q)print('==res:', res)#
# a = [1]
# a = [1, 2]
a=[1, 2, 3]
main(a, 0, len(a))class Solution:def permute(self, nums):""":type nums: List[int]:rtype: List[List[int]]"""def backtrack(first=0):# 所有数都填完了if first == n:res.append(nums.copy())for i in range(first, n):# 动态维护数组nums[first], nums[i] = nums[i], nums[first]# 继续递归填下一个数backtrack(first + 1)# 撤销操作nums[first], nums[i] = nums[i], nums[first]n = len(nums)res = []backtrack()return resa = [1, 2, 3]
sol = Solution()
res = sol.permute(a)
print('===res:', res)

4.递归实现快速幂

问题:求 a 的 b 次方对 p 取模的值

#a^b%p
def a_b_p(a,b,p):if b == 0:return 1elif b%2 == 1:#b是奇数return a*a_b_p(a, b-1, p)%pelse:#b是偶数temp = a_b_p(a, b//2, p)return (temp*temp)%pres = a_b_p(3,3,4)
print('==res:', res)

5.递归实现汉罗塔


#include <iostream>
#include <string>
#include <string.h>
#include <stdio.h>
using namespace std;
//a--from b--temp c--to
void hano(int n, char a, char b, char c);
int main(){hano(3, 'a', 'b', 'c');return 0;}
//a--from b--temp c--to
void hano(int n,char a, char b, char c){if(n==1){cout<<a<<"-->"<<c<<endl;}else{hano(n-1, a, c, b);//c为temp,a上面的n-1给bhano(1, a, b, c);//b为temp,a上面的1给chano(n-1, b, a, c);//a为temp,b上面的n-1给c}
}

加上盘子序号:

盘子从上到底是1到n

#include <iostream>
#include <string>
#include <string.h>
#include <stdio.h>
using namespace std;
//a--from b--temp c--to
void hano(int top, int n, char a, char b, char c);
int main(){hano(1, 3, 'a', 'b', 'c');return 0;}
//a--from b--temp c--to
void hano(int top, int n,char a, char b, char c){if(n==1){cout<<"盘子"<<top<<a<<"-->"<<c<<endl;}else{hano(top, n-1, a, c, b);//c为temp,a上面的n-1给bhano(top + n - 1, 1, a, b, c);//b为temp,a上面的1给chano(top, n-1, b, a, c);//a为temp,b上面的n-1给c}
}

递归理解以及时间复杂度计算相关推荐

  1. 【算法数据结构Java实现】递归的简单剖析及时间复杂度计算

    1.理解 对于递归函数的理解,我觉得是比较重要的,因为很多大神能把递归函数用的惟妙惟肖,不光是他们的编程功力高深,更主要是能理解这个算法.比较直白的理解是,如果一个事件的逻辑可以表示成,f(x)=nf ...

  2. 递归式的时间复杂度的计算

    递归算法的时间复杂度分析 在算法分析中,当一个算法中包含递归调用时,其时间复杂度的分析会转化为一个递归方程求解.实际上,这个问题是数学上求解渐近阶的问题,而递归方程的形式多种多样,其求解方法也是不一而 ...

  3. 解决递归求阶乘问题时间复杂度计算

    本问题源于<算法设计分析>,仔细并分析了阶乘问题时间复杂度计算.并为未来设计更好的算法,观测其时间复杂度打下良好的基础. 问题来源 求n!,n是大于或等于0的整数. 递归算法描述 int ...

  4. 解决递归中的重复计算问题

    一.重叠子问题 斐波那契数列没有求最值的问题,因此严格来说它不是最优解问题,当然也就不是动态规划问题.但它能帮助你理解什么是重叠子问题.首先,它的数学形式即递归表达是这样的: def Fibonacc ...

  5. 【算法设计与分析】16 分治策略:快速排序(快速排序的时间复杂度计算)

    上一篇文章学习了:[算法设计与分析]15 分治策略:芯片测试 文章目录 1. 快速排序的基本思想 1.2 时间复杂度的计算 1.21 最坏情况时间复杂度计算 1.22 最好情况时间复杂度 1.23 平 ...

  6. 算法 · 深入理解 Fibonacci 数列计算及黄金分割

    在自然界中,有一串数字我们时常能看到,它的前几项序列是: 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233- 如果用数学语言描述,它的递归形式是这样的 ...

  7. 数据结构--时间复杂度计算和空间复杂度计算篇

    时间复杂度和空间复杂度 一.时间复杂度 1.定义 2.三种时间复杂度 3.计算 *计算 #计算步骤 #常用技巧 #例题解析 二.空间复杂度 #定义 *计算 #计算步骤 #常用技巧 #例题解析 一.时间 ...

  8. 时间复杂度计算及空间复杂度计算

    目录 1.算法效率 2.时间复杂度 3.空间复杂度 4.大O渐进表示法 5.常见时间复杂度 常见复杂度对比 oj练习 1.算法效率 算法效率分析分为两种:第一种是时间效率,第二种是空间效率.时间效率被 ...

  9. 二分查找与时间复杂度计算分析

    二分查找: 二分查找又称折半查找,优点是比较次数少,查找速度快,平均性能好:其缺点是要求待查表为有序表,且插入删除困难.因此,折半查找方法适用于不经常变动而查找频繁的有序列表.   原理:假设表中元素 ...

最新文章

  1. 程序从命令行接收多个数字,求和之后输出结果。
  2. Winform中使用MQTTnet实现MQTT的服务端和客户端之间的通信以及将订阅的消息保存到文件
  3. linux查看硬盘smart_Linux检测磁盘坏道工具用什么命令
  4. linux 神的编辑器,编辑器之神-vim的使用,编辑器神-vim
  5. MariaDB之SQL语句基础
  6. GAN模型计算量减少至1/9!MIT韩松团队提出GAN压缩法,已开源
  7. OpenShift 4 - 为Gogs构建一个Operator
  8. Makefile:GCC CFLAGS变量和LDFLAGS变量
  9. amos调节变量怎么画_AMOS结构方程教程,SPSS调节效应分析操作与结果的详细解读...
  10. AfterEffects 不支持 MKV 格式的解决办法
  11. matlab里的dsolve,matlab_dsolve
  12. 挂名公司法人、董事、监事、高管的风险
  13. aspose设置两个word拼接后连续页码
  14. Windows 窗口发送消息参数详解
  15. 17正交矩阵和Gram-Schmidt正交化
  16. 项目管理系统(一)概述
  17. 正则中$1、$2的应用--日期格式化
  18. 你是怎样度过自己一生的?
  19. RNAseq生信分析流程简介
  20. 医学图像处理的SCI期刊和顶会

热门文章

  1. 支付宝wap支付过程中需要注意的坑
  2. 【内附源码和文档】在线课堂管理平台的设计与实现
  3. 15个有趣的工具和服务来监控您的Linux服务器
  4. 面霸篇:MySQL 35 卷
  5. Xcode文档阅读指南
  6. 基于java的校园二手平台系统毕业设计(项目报告+答辩PPT+源代码+数据库+截图+部署视频)
  7. linux中grub,nomodest,quiet等参数的含义,进入启动项之后黑屏的可能原因
  8. SLAM 反对称矩阵
  9. element组件自带的事件如何阻止其冒泡
  10. JBD Journaling block device