8 | 递归:如何用三行代码找到“最终推荐人“?


相信大家都见过,推荐用户注册返佣金的程序把?可以简单的概述为,用户A推荐用户B来注册,用户B推荐用户C来注册。那么,用户C的最终推荐人为用户A,用户B的最终推荐人也为用户A,而用户A没有最终推荐人。
一般来说,我们会将这层关系存入到数据库中。如图所示:

基于此,我们思考一下,如何根据用户ID来获取用户的最终推荐人呢?看下去吧,你会找到答案。

一、如何理解递归?

递归是一种使用很广泛的算法。在树和图中都有用到,比如前中后序遍历二叉树、DFS深度优先搜索。所以递归还是非常重要的,式后面数据结构学习的基础。

下面结合一个生活的实际场景,当你和你女朋友在电影院看电影时,你女朋友问你咱座在第几排。即使你想说怎么黑我怎么知道,也要憋住。常人的反映是,询问前面哪个人在第几排,然后在此基础上+1。前面那个人也学你,问了他前面那个人所在的排数,依次类推,当问到第一个人时,他前面已经没有人可以问了,于是乎,他告诉第二个人他在第1排,就这样一层层的返回,最后你就知道自己在哪一排啦!
虽然看着比较麻烦,当实现还是挺容易的。这是一个典型的递归求解问题的过程,去的过程叫"递",回来的过程叫"归"。基本上每个递归问题都可以用递推公式表示。刚刚的例子也不列外,用公式表示就是:
f(n) = f(n-1) + 1,其中,f(1) =1.其中f(n)表示你自己所在的排数,f(n-1)表示前一个人所在的排数。

二、递归需要满足哪些条件?

上面已经对递归做了深刻的描述,那什么问题才能使用递归来解决呢?需要满足下面三个条件:

1.一个问题的解可以分解成几个子问题的解

什么是子问题?就是数据规模更小的问题。结合前面电影院的例子,前面那个人问他前面那个人在哪一排就是子问题。

2.这个问题与分解之后的子问题,除了数据规模不同,求解思路完全一样

依然是那个电影院的例子,我计算我在那一排的方法,是在前面一排的基础上加1,前面那个人也是。

3.存在递归结束条件

如果没有递归结束条件,程序就永远不会停止,而堆栈的空间又有限(后面会说明),不支持这种操作,所以必须给定终止条件。电影院中,f(1)=1就是终止条件。

三、如何编写递归代码?

写递归代码的关键是写出递推公式,找到终止条件,最后只要将二者翻译成代码就好了!

四、递归代码需要警惕哪些问题?

1.警惕堆栈溢出

堆栈溢出会造成系统崩溃,后果非常严重。为什么递归代码容易造成堆栈溢出呢?那又如何预防这种情况发生?
系统栈或者虚拟机栈空间一般都不是很大。如果递归求解的数据规模很大,调用层次很深,一直压入栈中,就会有堆栈溢出的风险。

如何避免出现堆栈溢出呢?
可以限定递归的最大深度,当达到最大深度时,就结束递归操作。但是这种操作不能完全解决这个问题,因为我们事先不知道堆栈的可用大小,而递归的深度要根据堆栈的剩余空间来设定。实时计算这个数据也非常复杂,会影响代码的性能。

2.警惕重复计算

五、如何将递归代码转换成非递归代码?

  • 11
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值