4.递归计算

什么是递归?

递归应用非常广泛,比如 DFS 深度优先搜索、前中后序二叉树遍历等等。

假设一群人在排队,你不清楚自己前面有多少人,可以问前面的人:

image

但你前面也不清楚,整体过程就是递归:

https://www.processon.com/diagraming/606f9af5f346fb575c7168ab

如果用递推公式描述:

f(n)=f(n-1)+1 其中,f(1)=1

int f(int n) {
  if (n == 1) return 1;
  return f(n-1) + 1;
}

什么情况可以使用递归 ?

  1. 一个问题可以拆分成子问题.
  2. 这些问题求解思路相同(数据规模不同)
  3. 拥有终止条件

来看一个问题:

假如 n 个台阶(n >= 3),每次可以走 1 或 2 个台阶,走完 n 个台阶有多少种走法?
比如有 3 个台阶,可以 1,2 或者 2,1 :

f(n) = f(n-1)+f(n-2)  其中,f(1)=1,f(2)=2

int f(int n) {
  if (n == 1) return 1;
  if (n == 2) return 2;
  return f(n-1) + f(n-2);
}

常见问题

深度问题

重复计算问题


public int f(int n) {
  if (n == 1) return 1;
  if (n == 2) return 2;
  
  // hasSolvedList可以理解成一个Map,key是n,value是f(n)
  if (hasSolvedList.containsKey(n)) {
    return hasSolvedList.get(n);
  }
  
  int ret = f(n-1) + f(n-2);
  hasSolvedList.put(n, ret);
  return ret;
}

内存开销问题


int f(int n) {
  if (n == 1) return 1;
  return f(n-1) + 1;
}

空间复杂度:O(n)

将递归改写为非递归


int f(int n) {
  int ret = 1;
  for (int i = 2; i <= n; ++i) {
    ret = ret + 1;
  }
  return ret;
}
int f(int n) {
  if (n == 1) return 1;
  if (n == 2) return 2;
  
  int ret = 0;
  int pre = 2;
  int prepre = 1;
  for (int i = 3; i <= n; ++i) {
    ret = pre + prepre;
    prepre = pre;
    pre = ret;
  }
  return ret;
}

原理:函数调用底层原理是栈,可以利用 for 循环模拟入栈和出栈操作

1 个赞