于递归的理解及递归表达式复杂度分析(以求解最大公约数为例)

简介:

一,递归的四大基本法则:

①基准情形

基准情形是指那些不需要递归(不需要经过函数调用)之后就能退出的情况。它保证了递归的结束。

②不断推进

每一次递归之后,都要向着基准情形靠近,并且在靠近的过程中问题的规模越来越小。

③设计法则

书上说是:假设所有的递归调用都能运行-----“不是特别理解”

④合成效益法则

不要在不同的递归调用中做重复的工作。

 

二,实例

求解最大公约数--采用欧几里德算法

复制代码
 1 public static int gcd_recursive(int m, int n){
 2         if(m < n)
 3         {
 4             int tmp = m;
 5             m = n;
 6             n = tmp;
 7         }
 8         
 9         if(n == 0)
10             return m;//基准条件
11         return gcd_recursive(n, m%n);//不断推进
12     }
复制代码

分析:

第9-10行,是递归的基准条件。如果n=0,函数执行到10返回,不会执行到11行进行递归调用。

第11行,进行递归调用的地方。它是不断推进的,因为递归调用的参数朝着基准条件的方向变小了,如:

gcd_recursive(16,12)---->gcd_recursive(12,4)--->gcd_recursive(4,0)

每次递归调用,问题的规模越来越小了。

 

时间复杂度分析:

由公式: m%n<=m/2  可知:每次递归调用,问题的规模减小一半,类似于二分查找,这显然是一个非常好的算法。

由于第2-5行,花费的时间为常量时间,同样,在第9-10行的if语句判断也是花费的常量时间,在第11行进行递归调用,问题规模减少一半。

可得出,T(N) = T(N/2)+O(1)  推出:时间复杂度为O(logN)

-------------------------------------------------------------

递归逻辑的分析:

对于 gcd_recursive(16,12),第9行不成立,进入到第11行递归

对于 gcd_recursive(12,4), 第9行不成立,进入到第11行递归

对于gcd_recursive(4,0),直接执行到第9行返回,返回的值是4

返回之后,程序此时执行到gcd_recursive(12,4)中的第11行(即最后一行,不要被第9行干扰!第9行在gcd_recursive(12,4)中根本没有执行!!)

第11行代码是:gcd_recursive(4,0)

因为,gcd_recursive(4,0) 的结果是4,故 return gcd_recursive(4,0) 返回的结果也是 4。也即gcd_recursive(12,4)执行完成之后返回4。

 

由上面gcd_recursive(12,4)执行完成之后返回4,那么当gcd_recursive(16,12)的第11行代码 return gcd_recursive(12,4) 

执行完毕时,

整个程序结束了,返回的结果最终是4。

 

这种形式的递归又称为尾递归。可以看出,尾递归形式的程序最终返回的值就是 最里层递归调用得到的值。

 

在这篇文章中:字符数组转换成数字

递归的时间复杂度分析如下:

return recurse(c, len - 1) * 10 + (c[len - 1] - '0');

使得每次递归时,问题规模减小1,而后面的 + (c[len - 1] - '0') 操作可视为常量时间,故复杂度:

T(N) = T(N-1)+O(1)  得到T(N)=O(N)

 

结论:

对于递归操作而言,如果每次递归使问题的规模减半,而其他操作都是常数时间

T(N)=T(N/2)+O(1), 则T(N)=O(logN)

若每次递归使用问题的规模减1,而其他操作是常数时间

T(N)=T(N-1)+O(1),则T(N)=O(N)

 

若每次递归使问题的规模减半,而其他操作是线性时间,T(N) = T(N/2)+O(N)

则T(N)=O(NlogN)


本文转自hapjin博客园博客,原文链接:http://www.cnblogs.com/hapjin/p/5369881.html,如需转载请自行联系原作者

相关文章
|
4月前
最大公约数循环与递归版本
最大公约数循环与递归版本
21 0
|
6月前
|
算法 C++
C++快速幂(递归)
C++快速幂(递归)
|
11月前
|
机器学习/深度学习 存储 设计模式
从斐波那契数列到递归
大家好,我是王有志。今天我们要通过经典数学问【题斐波那契数列】来学习非常重要的编程技巧:递归。
89 1
从斐波那契数列到递归
算法学习--递归斐波那契数
算法学习--递归斐波那契数
算法学习--递归求n的阶乘
算法学习--递归求n的阶乘
算法--递归辗转相除法求最大公约数
算法--递归辗转相除法求最大公约数
你是真的“C”——函数递归详解青蛙跳台阶
手把手教学——函数递归详解汉诺塔+青蛙跳台阶问题
80 0
你是真的“C”——函数递归详解青蛙跳台阶
|
算法
【递归与递推 3】AcWing 717. 简单斐波那契(求解斐波那契数列的若干方法)
【递归与递推 3】AcWing 717. 简单斐波那契(求解斐波那契数列的若干方法)
【递归与递推 3】AcWing 717. 简单斐波那契(求解斐波那契数列的若干方法)
|
算法
递归+回溯求解数独问题
导读:回溯是常用的算法理论之一,很多规模较大、直接分析较为复杂的问题都可以考虑用回溯求解,例如N皇后问题、骑士周游和走迷宫问题等。本质上,回溯问题是一种优化后的暴力求解,通过及时的剪枝和启发式的寻找最优路径,可以有效加速求解过程。回溯还常常与递归搭配使用
131 0
递归+回溯求解数独问题