递归
-
递归设计思路
1.找重复 (子问题) 2.找重复中的变化量 -> 参数 3.找参数变化趋势 -> 设计出口 换句话说就是把一个任务划一刀分成两份,自己做一部分,委托别人做另外一部分。
-
练习策略
1.循环改递归 2.经典递归 3.大量练习,总结规律,掌握套路
-
递归的定义
1.自身调用自身
public class Main {
public static void main(String[] args) {
function(10);
}
static void function(int i) {
if (i == 0) { //退出递归的条件
return;
}
function(i - 1); //自身调用自身
}
}
- 练习
- 求n*(n-1)的阶乘
public class Main {
public static void main(String[] args) {
f1(10);
}
/*
* f1(n):求n的阶乘 --> 求n-1的阶乘
* 找重复:n*(n-1)的阶乘,求(n-1)是问题的重复
* 找变化:变化的量应该作为参数
* 找边界:出口
*/
static int f1(int n){
if (n == 1) {
return 1; //因为1的阶乘就是1
}
return n * f1(n -1);
}
}
- 打印i到j。 (可以使用for循环,但是此处是为了练习递归的思想)
public class Main {
public static void main(String[] args) {
f2(1,10);
}
/*
* 找重复:
* 找变化:变化的量应该作为参数
* 找边界:出口
*/
static void f2(int i, int j){
if (i > j) {
return ;
}
System.out.println(i);
f2(i+1, j);
}
}
- 对arr的所有元素求和。(可以使用for循环,但是此处是为了练习递归的思想)
public class Main {
public static void main(String[] args){
int result = f3(new int [] {1,2,3,4,5}, 0);
System.out.println(result);
}
/*
* 找重复:
* 找变化:变化的量应该作为参数,此处变化的量应该是数组的索引值
* 找边界:出口,当begin开始的索引等于arr.length-1时,后面没有值了
*/
static int f3(int [] arr ,int begin){
if (begin == arr.length-1) {
return arr[begin];
}
return arr[begin] + f3(arr, begin +1 );
}
}
- 斐波那契数列F(n) = F(n-1) + F(n-2)。
public class Main {
public static void main(String[] args) {
int result =fib(5);
System.out.println(result);
}
static int fib(int n){
if (n ==1 || n == 2) {
return 1;
}
return fib(n -1 ) + fib(n - 2);
}
}
Tips:
1. 递归可以分解成直接量和小规模问题。例如前面的求n的阶乘。
2. 递归也可以分解成多个小规模问题。如斐波那契数列。F(n) = F(n-1) + F(n-2)。
5. 汉诺塔问题。 (1到N从A移动到B,C作为辅助)
思路:
1). 第1个到N-1个盘子从A移动到C,B做为辅助。
2). 把最底下最大那个盘子N从A移到B。
3). 把第1个到N-1盘子从C移动到B,此时A为空的了,因此作为作为辅助来接收1-N-2的盘子。一直循环即可,保持B上的盘子不动。
代码实现如下所示:
public class Main {
public static void main(String[] args) {
printHanoiTower(3, "A", "B", "C");
}
/**
*
* @Title: printHanoiTower
* @Description: 对A柱子上的盘子移动到B柱子上
* @param N 初始从小到大的盘子
* @param from 原始柱子
* @param to 目标柱子
* @param help 辅助柱子
* @return void 无
*/
static void printHanoiTower(int N,String from, String to, String help){
if (N == 1) {
System.out.println("move" + N + "from" + from + "to" + to);
return;
}
else{
printHanoiTower(N -1, from, help, to);
System.out.println("move" + N + "from" + from + "to" + to);
printHanoiTower(N-1, help, to, from);
}
}
}
- 总结:
- 找重复:
1). 找到一种划分的方法。
2). 找到递推公式或等价替换.
3). 都是父类问题转化为求解子类问题。 - 找变化:
变化的量通常都是作为参数。 - 找出口:
临界的值。
来源:CSDN
作者:是白衣呀
链接:https://blog.csdn.net/weixin_44875986/article/details/104397305