递归的理解:
在电影院中问前一排的人:“自己是第几排”,前一排的人做同样的事:问前一排“自己是第几排”,一直到第一排(递),然后从第一排向后一排排地把数字传回来(归)
递推公式:
1 | f(n)=f(n-1)+1 其中,f(1)=1 //f(n)是自己所在的排数,f(n-1)是前一排的排数,f(1)=1是第一排的排数 |
代码:
1 | int f(int n) { |
递归的优缺点:
优点:代码的表达力很强,写起来简洁
缺点:空间复杂度高、有堆栈溢出风险
java.lang.StackOverflowError
、存在重复计算、过多的函数调用会耗时较多等问题。针对电影院这个递归的堆栈溢出问题可通过限制递归调用的最大深度的方式解决
1
2
3
4
5
6
7
8
9
10int depth = 0; // 递归的深度
// 设定n>0
int f(int n) {
++depth;
if (depth > 1000) throw exception;
if (n == 1) return 1;
return f(n-1) + 1;
}
递归的问题:
问题一:有n个台阶,每次可以跨1个台阶或者2个台阶的走,问走完n个台阶有多少种走法?
递推过程:
1 | f(1) = 1; //n=1时,一步1个台阶走完 |
伪代码如下:
1 | int f(int n) { |
为了避免重复计算,可用散列表来保存已经求解过的f(k),递归调用f(k)时先检查是否计算过了
1 | public int f(int n) { |
问题二:推荐注册返佣金,给定一个用户的ID,查找这个用户的“最终推荐人”
推荐关系的数据库关系(D -> C -> B -> A):
actor_id | referre_id |
---|---|
B | A |
C | B |
D | C |
解决方法:
1 | long findRootReferrerId(long actorId) { |
学自 王争——《数据结构与算法之美》