machao07 / interview-questions

前端技术栈相关面试知识点( Vue、React、Typescript、JavaScript...),喜欢请点start

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

递归 & 尾递归

machao07 opened this issue · comments

一、递归

递归的特点

  • 自身调用:原问题可以分解为子问题,子问题和原问题的求解方法是一致的,即都是调用自身的同一个函数
  • 终止条件:递归必须有一个终止的条件,即不能无限循环地调用本身

实现从1到n的累加

function sum(n) {
    if (n === 1) return n;
    return sum(n - 1) + n
}

sum(5) // 15

分析

image

  • sum(5)时,先sum(5)入栈,然后原问题sum(5)拆分为子问题sum(4),再入栈,直到终止条件sum(n=1)=1,就开始出栈
  • sum(1)出栈后,sum(2)开始出栈,接着sum(3)
  • sum(1)就是后进先出,sum(5)是先进后出,递归过程可以理解为栈出入过程

递归解题思路

  • 定义函数功能
  • 寻找递归终止条件
  • 递推函数的等价关系式

例阶乘

function factorial(n) {
    if (n === 1) return 1;
    return n * factorial(n - 1)
}

factorial(5) // 120
// =>
5 * factorial(4)
5 * (4 * factorial(3))
5 * (4 * (3 * factorial(2)))
5 * (4 * (3 * (2 * factorial(1))))
5 * (4 * (3 * (2 * 1)))
5 * (4 * (3 * 2))
5 * (4 * 6)
5 * 24
120

二、尾递归

尾递归的特点

  • 在尾部调用的是函数自身
  • 可通过优化,使得计算仅占用常量栈空间
function factorial(n, total) {
    if (n === 1) return total
    return factorial(n - 1, n * total)
}

factorial(5, 1) // 120
// =>
factorial(4, 5)  // 5*1
factorial(3, 20) // 4*5
factorial(2, 60) // 3*20
factorial(1, 120) // 2*60