Java数据结构与算法->递归

感情迁移 提交于 2020-02-21 11:25:26

递归

  1. 递归设计思路

     1.找重复 (子问题)
     2.找重复中的变化量 -> 参数
     3.找参数变化趋势 -> 设计出口
     换句话说就是把一个任务划一刀分成两份,自己做一部分,委托别人做另外一部分。
    
  2. 练习策略

     1.循环改递归
     2.经典递归
     3.大量练习,总结规律,掌握套路
    
  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); //自身调用自身
	}
}
  1. 练习
    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);
	}
}
  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);
	}
}
  1. 对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 );
	}
}
  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. 找重复:
    1). 找到一种划分的方法。
    2). 找到递推公式或等价替换.
    3). 都是父类问题转化为求解子类问题。
  3. 找变化:
    变化的量通常都是作为参数。
  4. 找出口:
    临界的值。
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!