浅谈巧妙算法:递归(2)

2021.7.29
在递归(1)的文章里,简单阐述了线性递归的正确性和有穷性,并以数组求和作为例子来体会递归。下面一起来分析一下递归的时间复杂度和空间复杂度。

递归分析

由于递归算法的时空复杂度与常规算法很不一样,有着自身的规律与特定技巧,以下来介绍两种方法:

*递归跟踪

具体地,按照以下原则,将递归算法执行过程转变为图的形势:

1.算法的每一递归实例都表示为一个方框,其中注明了该实例调用的参数
2.若实例M调用实例N,则在M与N对应的方框之间添加一条有向联线

用以上原则来分析数组求和的递归写法(见文章递归(1)),整个算法所需要的时间应该是递归实例的创建、执行、销毁的时间总和。而创建、销毁的过程时间成本近似为常数,所以我们只需要统计各递归实例中非递归部分调用的时间(即执行步骤)即可。

int sum(int A[], int n){
	if(n<1) return 0;
	else return sum(A, n-1) + A[n-1];
}

时间复杂度:分析数组求和的例子,该算法所涉及的计算无非三类:判断n是否为零,累加sum(n-1)与A[n-1],返回当前总和。且至多各执行一次,即计算时间应该为常数O(3),递归深度为n+1,所以时间复杂度为:(n+1)*O(3)=O(n)。

空间复杂度:sum()算法在创建了最后一个递归实例时,占用的空间达到最大,等于所有递归实例各自所占空间量的总和。这里每一递归实例所存放的数据,就是调用参数和用于累加总和的临时变量。只需要常数规模的空间O(n)。

*递推方程

该方法与递归跟踪相反。是通过对递归模式的数学归纳,导出复杂度定界函数的递推方程(组)及其边界条件。类似于高中数学中的斐波那契数列。
在此,仍以以上数组求和的代码为例:

int sum(int A[], int n){
	if(n<1) return 0;
	else return sum(A, n-1) + A[n-1];
}

通过代码我们知道,求解sum(A, n)所需要的时间,等于求解sum(A,n-1)所需的时间,另加一次整数加法的时间。
即T(n)=T(n-1)+O(1)=T(n-1)+c1(常数)
当抵达递归基时,求解平凡问题所需时间为常数,
即T(0)=O(1)=c2(常数)
联立二式可得:T(n)=O(n)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值