递归
核心思想是 缩小范围(划分更小子问题)每一次递归会缩小子问题的范围在根据问题判断采用那种思路
切蛋糕试
单分支
分节成常数和一个小范围的问题 (划一刀思想)
阶乘
> 要求出一个数的阶乘 我们需要先取出第一个数 和后面的数相乘 这就将
我们要所求n的阶乘从 n 变成了 n-1 缩小了 n的范围
我们设定 函数 f(n)为求 n的阶乘 那么f(n-1)就是求n-1的阶乘 那马 n!= n*f(n-1)
public class 阶乘 {
public static void main(String[] args) {
int i = fun1(10);
System.out.println(i);
}
static int fun1(int i){
if (i==1){
return 1;
}
return i*fun1(i-1);
}
}
公式型
分解成多个小范围的子问题 (采用寻找递推公式 和等价代换)
/**
* 裴波那契序列 1 1 2 3 5 8 13
* 符合 f(n)=f(n-1)+f(n-2) (n>2)
*/
public class 裴波那契序列 {
public static void main(String[] args) {
System.out.println(fun(7)); //13
}
static int fun(int n){
if (n==1||n==2){
return 1;
}
return fun(n-1)+fun(n-2);
}
}
//辗转相除 用大叔除以小数 的到余数 余数为0则 最大公约数为 除数 若有余数 则 拿除数 在除以余数 直到 余数为 0
public class 最大公约数 {
public static void main(String[] args) {
int fun = fun(10, 3);
System.out.println(fun);
}
static int fun(int m,int n){
if (n == 0){
return m;
}
return fun(n,m%n);
}
}
等价于型
将一个长度为 n 的数组排序 等价于 将一个 n-1 长度的数组排序 当 n-1 数组有序的时 将 第 n 个放到合适的位置
插入排序
public class 插入排序 {
public static void main(String[] args) {
int[] arr={1,3,2,6,3,4,7,9};
fun(arr,1);
System.out.println(Arrays.toString(arr));
}
static void fun(int[] arr,int k){
if (k==arr.length-1){
return;
}
int n=k;
while (arr[n -1]>arr[n]&&n>=0){
int temp=arr[n-1];
arr[n-1]=arr[n];
arr[n]=temp;
n--;
}
fun(arr,k+1);
}
}
习题
相传在古印度圣庙中,有一种被称为汉诺塔(Hanoi)的游戏。该游戏是在一块铜板装置上,有三根杆(编号A、B、C),在A杆自下而上、由大到小按顺序放置64个金盘(如下图)。游戏的目标:把A杆上的金盘全部移到C杆上,并仍保持原有顺序叠好。操作规则:每次只能移动一个盘子,并且在移动过程中三根杆上都始终保持大盘在下,小盘在上,操作过程中盘子可以置于A、B、C任一杆上。
做题之前先分析一下 当 盘子数为三的时候如何移到C 在接着看
分析完了我们再来考虑一下 这是一个什么问题
首先 第1个盘子a->c
第2个盘子a->b
第1个盘子c->b //这个时候我们发现 n-1个盘子都移动到了 辅助盘 A 另外两个盘相当于空(因为最后一个盘子最大 其他盘子都可以放上去 )
第3个盘子a->c 将最大的 盘子移到到 C
第1个盘子b->a //这里 发现 就是通过 A 将 B 中的盘子移到 C
第2个盘子b->c
第1个盘子a->c
于是我们总结 出一个规律就是 这个问题 是
要 ** 盘子要移动的柱子 ** 上的n-1 个盘子 移动到一个**辅助的柱子**上
再将 第 n 个盘子从要**盘子要移动的柱子**上移到的**最终的柱子**上
后将 ** 盘子要移动的柱子 ** 上的n-2 个盘子 移动到一个**辅助的柱子**上
再将 第 n-1 个盘子从要**盘子要移动的柱子**上移到的**最终的柱子**上 。。。。。。
发现 其子问题相同 只不过是 柱子的编号不一样但性质是一样的 采用递归 在递归时交换参数 在分析
/**
* 吧n个盘子从A移到 C
* 等价于
* 1,将 n-1 个盘子 通过 C 移到 B
* 2,将 第 n个盘子移动到 从 A 移到到 C
* 3,将 n-1的盘子从 B 通过 A 移到 C
*/
public class 汉罗塔 {
public static void main(String[] args) {
fun(3,'a','b','c');
}
/**
* 把n个盘子从A移到 C
* 将 n 个盘子移动到 C
* 等价于
* 1,将 n-1 个盘子 通过C 移到 B
* 2,将 第 n个盘子移动到 从 A 移到到 C
* 3,将 n-1的盘子从 B 通过 A 移到 C
*/
static void fun(int n, char A,char B,char C){
if (n==1){
System.out.println("第"+n+"个盘子"+A+"->"+C);
return;
}
fun(n-1,A,C,B);
System.out.println("第"+n+"个盘子"+A+"->"+C);
fun(n-1,B,A,C);
}
}
urn;
}
fun(n-1,A,C,B);
System.out.println(“第”+n+“个盘子”+A+"->"+C);
fun(n-1,B,A,C);
}
}
递归 在传递参数的时候不要使用 ++等 因为有时候递归会回过来在执行之前没执行玩的语句 使用++会导致这一层的变量值发生变化