递归调用是指一种通过重复将问题分解为同类的子问题而解决问题的方法。其实就是不断调用自身。
递归原理见:递归原理详解.
1 斐波那契数列
斐波那契数列(Fibonacci sequence),又称黄金分割数列、因数学家莱昂纳多·斐波那契(Leonardoda Fibonacci)以兔子繁殖为例子而引入,故又称为“兔子数列”,指的是这样一个数列:0、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
,
n
∈
N
∗
)
F(1)=1,F(2)=1, F(n)=F(n - 1)+F(n - 2)(n ≥ 3,n ∈ N^*)
F(1)=1,F(2)=1,F(n)=F(n−1)+F(n−2)(n≥3,n∈N∗)
代码实现如下
public int fib(int n) {
if (n <= 0){
return 0;
}
if (n == 1){
return 1;
}
return (fib(n -1) + fib(n - 2)) % 1000000007;
}
2 n
的阶乘
任何大于等于1 的自然数
n
n
n阶乘表示方法:
n
!
=
n
×
(
n
−
1
)
!
(
n
>
1
)
0
!
=
1
(
n
=
0
)
n!=n \times(n-1)! \quad (n > 1) \\ 0! = 1 \quad (n = 0)
n!=n×(n−1)!(n>1)0!=1(n=0)
阶乘亦可以递归方式定义:0!=1,n!=(n-1)!×n。
代码实现如下
public Integer factorial(int n){
if (n == 1){
return 1;
}
return n * factorial(n - 1);
}
3汉若塔问题
3.1问题描述
来源力扣面试题08.06.汉若塔问题。
在经典汉诺塔问题中,有 3 根柱子及 N 个不同大小的穿孔圆盘,盘子可以滑入任意一根柱子。一开始,所有盘子自上而下按升序依次套在第一根柱子上(即每一个盘子只能放在更大的盘子上面)。移动圆盘时受到以下限制:
- 每次只能移动一个盘子
- 盘子只能从柱子顶端滑出移到下一根柱子
- 盘子只能叠在比它大的盘子上。
3.2代码思路
问题分解: 当只有两个盘子时
- 把A上的盘子放在B上
- 把A上的盘子放在C上
- 把B上的盘子放在C上
当有n个盘子时
- 把A上的n-1个盘子放在B上
- 把A上的最后一个盘子放在C上
- 把B上的n-1个盘子放在C上
3.3代码实现
public void hanota(List<Integer> A, List<Integer> B, List<Integer> C) {
move(A.size(), A, B, C);
}
void move(int n, List<Integer> A, List<Integer> B, List<Integer> C){
if (n == 1){
C.add(A.get(A.size() - 1));
A.remove(A.size() - 1);
return;
}
move(n - 1, A, C, B); // A经过辅助C放到B上
C.add(A.get(A.size() - 1)); // 把A的最上面盘子放在C上
A.remove( A.size() - 1); // 把A的最上面盘子移除(因为已经放在C上了)
move(n - 1, B, A, C); // 把B经过辅助A放在C上
}