递归分享

递归

刚开始学递归的时候,总觉得递归太难理解了,为什么这段代码就可以这样执行,为什么我们假设这个函数有这样的功能,他就真的有这个功能,他的临界点到底怎么寻找,循环和递归有什么区别?

什么是递归

在这里插入图片描述

递归的定义就是在函数的定义中使用函数自身的方法。
递归就是有去(递去)有回(归来)
英文的Recursion从词源上分析只是"re- (again)" + “curs- (come, happen)” 也就是重复发生,再次重现的意思。

我的理解就是 想去看海,便从家里出发,向着海的方向走,走了10公里,发现没有到,便继续走,20公里还没到,30…40…50…,在走到100公里的时候,终于看到海了,心满意足,便从海边回家,10公里,20公里…到家了!也知道了家到海边有多远
从家里到海边的过程便是递去,到了海边,这就是一个临界点,从海边回到家里,便是归来
回到家,家人问你到底走了多远到了海边,你便可以回答走了多远,
这就是递归有去便有回

递归与循环的区别

递归是把问题看成一个整体,逐级分而解决,而循环是把问题看成是一个个独立的个体
递归其实和循环是非常像的,循环都可以改写成递归,递归未必能改写成循环,这是一个充分不必要的条件。

那么,有了循环,为什么还要用递归呢??在某些情况下(费波纳切数列,汉诺塔),使用递归会比循环简单很多很多

用递归的解决思路

用递归解决问题需要明确几个步骤。

  • 递归出口(终止递归的条件)
  • 递归表达式(规律)
  • 假定我们已经解决了问题,并且有了解决这个问题的函数。
  • 如何将问题从 n 的规模降到 n - 1 的规模。
  • 递归的出口是什么,也就是当问题规模已经降到最小的时候,我们如何解决它

实例

实例一:下面的代码就是一个简单的递归函数,在这个函数里面调用了自己,会一直循环往复,没有止境,这种叫做死递归
	function fn(){
             console.log(1)
            fn()
         }
        // fn();//调用fn,执行fn里面的代码,打印1,又执行fn,又打印1,又执行fn,......
案例二:简单实现一个递归

                ==>需求:求1到5的和
思路                ==>先得到1+2=3
                    ==>再算3+3=6
                    ==>再算6+4=10
                    ==>再算10+5=15
                    ==>结束
                   
//开始书写:写递归函数先要写一个结束条件(为了避免出现"死递归")
function add(n){
                 function add(n){
                 //add(n)这个函数的作用是:1到n的累加和
                 //当n===1的时候就要结束
                 if(n===1){   //当n等于1时,终止并返回
                     return 1;
                 }else{
                     return add(n-1)+n; //add(n-1)+n可以理解为 (5-1)+5,(4-1)+4,(3-1)+3...
                 }
             }
             console.log(add(5));
案例3  算出n-100的阶乘
function factorial(n){
                //思路:先想到结束递归的条件,因为是n到100,所以出口就是 n==100;时结束
                if( n == 100){
                    return 100;
                }else{     //不满足时
                    return factorial(n+1)*n
                }
            }
        console.log(factorial(n))

案例4 计算Fibonacci sequence的第N项:
            斐波那契数列(Fibonacci sequence),又称黄金分割数列、
            因数学家列昂纳多·斐波那契(Leonardoda Fibonacci)以兔子繁殖为例子而引入,故又称为“兔子数列”,
            指的是这样一个数列:1、1、2、3、5、8、13、21、34、……在数学上,
            斐波那契数列以如下被以递推的方法定义:F(1)=1,F(2)=1, F(n)=F(n - 1)+F(n - 2)(n ≥ 3)

规律就是:前两项之和等于第三项
  	1 + 1 = 2
    2 + 3 = 5
    13 + 21 = 34
function fibonacci(n){
            if(n==1){
                return 1;
            }
            if(n==2){
                return 1;
            }
            //n = 3 :return fibonacci(2)+fibonacci(1)
            //n = 4 :return fibonacci(3)+fibonacci(2)
            //由此得出规律
            return fibonacci(n-1)+fibonacci(n-2);
        }
        console.log(fibonacci(6))


理解递归的关键在于两点:1)把问题分解成小部分,用函数写出来,然后一层一层“重新组合”起来2)有一个基本情况即Base case,当到达基本情况时,就会触底,递归调用也就结束了。 例如,类似( ( ( ( () ) ) ) )这种嵌套的括号一样。每一次的行为都是相同的,就是用括号()把内部的东西括起来,一层一层组合起来(RecursiveStep)。但是会有一种BaseCase,那就是(),括号内部为空,这样就会触底,再一层层的从括号中跳出来。即分解了问题,又重组了答案。 所以,在用递归去写函数时,一定要有一个基础情况,放在函数的第一步,然后不是基础情况下递归调用,重复类似操作。

什么时候需要用递归

递归适合用在:
数据的结构形式是按照递归定义的,比如单链表,二叉树,斐波那契数列等;
数据的结构形式不是按照递归定义的,但是用递归求解比用循环求解更加简单,比如汉诺塔问题,四重及以上循环问题。
循环适合用在:
数据的结构形式不是按照递归定义的,使用循环就能够轻松解决的问题,比如一重循环、二重循环、三重循环。

部分资料来源链接:https://www.zhihu.com/question/20507130/answer/29178379;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值