Table of Contents
一、递归的基本概念
-
递归的定义
一个过程或函数在其定义或说明中有直接或间接调用自身的一种方法,它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解,递归策略只需少量的程序就可描述出解题过程所需要的多次重复计算,大大地减少了程序的代码量。递归的能力在于用有限的语句来定义对象的无限集合。一般来说,递归需要有边界条件、递归前进段和递归返回段。当边界条件不满足时,递归前进;当边界条件满足时,递归返回。
可以不用看,反正也没人愿意看,直接看一句话概括他不香吗,咳咳简单说就是 自己调用自己的函数
要李姐递归首先要李姐递归(doge)
二、递归的应用
首先,相信大家第一次接触到递归都是 汉诺塔,或者是 斐波那契数字等等,这里就以汉诺塔作为例子实现代码如下:
import java.util.Scanner;
class Solution {
public void hanoi(char a, char b, char c, int n) {
if (n == 0) return;
hanoi(a, c, b, n - 1);
System.out.println("将" + n + "从" + a + "移动到" + c);
hanoi(c, b, a, n - 1);
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
new Solution().hanoi('a', 'b', 'c', n);
}
}
我们可以将递归的过程理解成为一个栈。遵循着 FILO
的原则,如图所示,我们需要解决问题 1,但是结局问题 1,需要先解决问题 2,要解决问题2 ……依次类推,那我们需要首先解决问题 4,才能解决问题 3,从而解决问题 2,最后才能结局问题 1。
那我们先将 1 放入栈中,然后解决问题 2,同理 后面以此类推。最终解决了问题 4,由问题 4,得到的答案解决问题 3,以此类推,最终得到问题 1的答案。
三、怎么写递归
在学习如何书写递归之前,我想先说明一下,什么时候去使用递归。
我认为满足以下三点即可。
- 一个问题的解可以分解为几个子问题的解;
- 这个问题与分解之后的子问题求解思路完全一致;
- 一定有一个终止条件。
理解了以上三点就可以很轻松的写出递归了
-
首先找到退出(结束递归)的条件
-
这点我认为是最重要的,因为递归如果没有截止条件的话,最终会导致栈溢出。
-
不相信的话,可以试试项目这段代码
public void test(){ test(); }
-
-
然后找到子问题的相同点(解决方法),
-
最后调用自身即可
四、例题
-
class Solution { public int fib(int n) { if (n == 0) return 0; if (n == 1) return 1; return fib(n - 1) + fib(n - 2); } }
-
class Solution { public int multiply(int A, int B) { return A > B ? fun(B, A) : fun(A, B); } public int fun(int a, int b) { if (a == 0) return 0; if (a == 1) return b; return b + fun(a - 1, b); } }
最后:递归还有很多的用处,例如树的遍历、DFS、回溯等等。