# 递归
## 简答题
1. 九九乘法表
```
function num(nums){
    if(nums==1){
        console.log("1x1=1")
    }else{
        num(nums-1)
        for(var i=1,str='';i<=nums;i++){
            str += `${i}x${nums}=`+i*nums+' '
        }
        console.log(str)
    }
}
num(9)
// 循环
for(var i=1;i<10;i++){
    let str = ''
    for(var j=1;j<10;j++){
        if(i>=j){
            str += `${j}x${i}=`+i*j+' '
        }
    }
    console.log(str)
}
```


2. 定义一个函数 实现n的阶乘
```
 function jc(n){
     if(n<=1){
      return 1;
     }else{
      return n*arguments.callee(n+1);
     }
    }

```




3. 一只青蛙可以一次跳 1 级台阶或者一次跳 2 级台阶，例如：
    跳上第 1 级台阶只有一种跳法：直接跳 1 级即可。 跳上第 2 级台阶有两种跳法：每次跳 1 级，跳
    两次；或者一次跳 2 级。 问要跳上第 n 级台阶有多少种跳法？
```

 function ge(n){  
     if(n==0){
      return 0;
     }else if(n==1){
      return 1;
     }else if(n==2){
      return 2;
     }
     return ge(n-1)+ge(n-2);
    }


   ```





4. 编写一个函数，输入n为偶数时，调用函数求1/2+1/4+…+1/n,当输入n为奇数时，调用函数求/1+1/3+…+1/n;
```
function num(nums){
    if(nums==1){
        console.log("1x1=1")
    }else{
        num(nums-1)
        for(var i=1,str='';i<=nums;i++){
            str += `${i}x${nums}=`+i*nums+' '
        }
        console.log(str)
    }
}
num(9)
// 循环
for(var i=1;i<10;i++){
    let str = ''
    for(var j=1;j<10;j++){
        if(i>=j){
            str += `${j}x${i}=`+i*j+' '
        }
    }
    console.log(str)
}


```




5. 1+2+3+4+....+100(n)求和
```
 function dg(x){   //第一题
     if(x==1)return 1;
     return dg(x-1)+x;
    }
    var lj=dg(100);
    console.log(lj)

```







6. 细胞分裂 有一个细胞 每一个小时分裂一次，一次分裂一个子细胞，第三个小时后会死亡。那么n个小时候有多少细胞？

```
// 每三个小时为一个周期 ， 第四个小时就 go die 了。
// 方法一
// 第一个小时，只有a态细胞；第二个小时，a态细胞分裂，原来的a态细胞变成了b态细胞，分裂出来的细胞变成了新的a态细胞；第三个小时，a态细胞继续分裂变成b态细胞和新的a态细胞，b态细胞分裂变成c态细胞和a态细胞；第四个小时，a、b、c态细胞都会分裂，并且按照之前的规律转变。得出下面的结论
// a 初始态 一个小时 前一个小时的 a+b+c
// b 幼年态 两个小时 前一个小时的 a
// c 成熟态 三个小时 前一个小时的 b
function allCell(n){
    // a态细胞
    let aCell = function(n){
        if(n==1){
            return 1;
        }else{
            return aCell(n-1)+bCell(n-1)+cCell(n-1);
        }
    }
    // b态细胞
    let bCell = function(n){
        if(n==1){
            return 0;
        }else{
            return aCell(n-1);
        }
    }
    // c态细胞
    let cCell = function(n){
        if(n==1||n==2){
            return 0;
        }else{
            return bCell(n-1);
        }
    }
    return aCell(n)+bCell(n)+cCell(n)
}
console.log(allCell(10))
// 方法二
// 这个方法就是分成了 活着的 和 死亡的
function cell(hour){
    // 活着的细胞
    function livecell(hour){
        if(hour<4){
            // 前三个小时没有死亡的细胞 成2的n-1次方增长
            return Math.pow(2,hour-1)
        }else{
            // 从第四个小时开始有死亡的细胞 
            // 活着的细胞 = 前一个小时活着的细胞 - 这个小时死去的细胞
            return livecell(hour-1)*2 - diecell(hour)
        }
    }
    // 死亡的细胞
    function diecell(hour){
        if(hour<4){
            // 前三个小时没有死亡的细胞
            return 0
        }else{
            // 因为三个小时一个周期
            // 也就是每三个小时,(n-3)时的细胞就会死完
            // 那么 这个小时(n)死去的细胞 + 上个小时(n-1)死去的细胞 + 前两个小时(n-2)死去的细胞 = 前三个小时(n-3)活着的细胞
            return livecell(hour-3) - diecell(hour-1) - diecell(hour-2)
        }
    }
    return livecell(hour)
}
console.log(cell(10))


```



7. 有 64 个格子，第一个格子放一粒麦子，第二个放2粒，第三个放4粒...每个格子都是前边的两倍。一共有多少粒？

```
let sum = 0
let start = 1;
let end = 0;
function tow(){
    if(end>=64){
        return false
    }
    sum+=start
    start*=2
    end++
    tow()
}
tow()
console.log(sum)

```



8. 输出斐波那契数列
```
// 递归
    let a = 0;
    function tu(num){
        a++
        if(num==1||num==2){
            return 1
        }
        let nums = tu(num-1)+tu(num-2)
        return nums
    }
    console.log(tu(8),a)
// 闭包解决
    // 也就是存在数组中，再次循环时，如果数组中已经存在，就返回数组中的值，大大减少了递归调用函数的次数
    var count2=0;
    var fiba = (function(){
        var arr = [0,1,1];   //第0位只是占位，从第一位开始算起
        return function(n){
            count2++;   
            var res=arr[n]; 
            if(res){// 如果arr中存在，返回这个值
                console.log(res,'----')
                return res;
            }else{
                console.log(arr[n],'+++++')
                arr[n]=fiba(n-1)+fiba(n-2);
                return arr[n];
            }   
        }
    })();
    console.log(fiba(8),count2)
// 普通
    // 普通循环解决这个问题是性能最好的。
    let a = 1;
    let b = 1
    let c;
    function tu(num){
        for(let i=0;i<num-2;i++){
            c = a+b;
            a = b;
            b = c
        }
        return c;
    }
    console.log(tu(8))
    
```



9. 
10. 下面代码导致的问题如何解决
```
function factorial(num){ 
 if (num <= 1){ 
 return 1; 
 } else { 
 return num * factorial(num-1); 
 } 
}
var anotherFactorial = factorial; 
factorial = null; 
alert(anotherFactorial(4));

```
答案
我们知道，arguments.callee 是一个指向正在执行的函数的指针，因此可以用它来实现对函数
的递归调用，例如：
```
function factorial(num){ 
 if (num <= 1){ 
 return 1; 
 } else { 
 return num * arguments.callee(num-1); 
 } 
}

```




11. 猴子吃桃问题：猴子第一天摘下若干个桃子， 当即吃了一半，还不过瘾，又多吃了一个; 第二天早上又将剩下的桃子吃掉一半，又多吃了一个。
* 以后每天早上都吃了前一天剩下的一半零一个。 到第10天早上想再吃时，见只剩下一个桃子了。 求第一天共摘了多少。


程序分析：采取逆向思维的方法，从后往前推断。

// 倒数第1 2 3 4 5 6 天
// 桃数量1 4 10 22 46 94
// 采用递归的方法



```
 // 返回第n天的桃子数量
function getValue(n){
    if (n == 1) {
            return 1;
        }
        return (getValue(n - 1) + 1) * 2;
}

 for (int i = 1; i < 11; i++) {
            console.log("第" + i + "天\t" + getValue(i) + "颗");
        }


```