递归
1、递归的基本概念:程序调用自身的编程技巧称为递归,是函数自己调用自己.一个函数在其定义中直接或间接调用自身的一种方法,它通常把一个大型的复杂的问题转化为一个与原问题相似的规模较小的问题来解决,可以极大的减少代码量.递归的能力在于用有限的语句来定义对象的无限集合。
2、迭代:利用变量的原值推算出变量的一个新值.如果递归是自己调用自己的话,迭代就是A不停的调用B。
3、递归和迭代的区别:递归中一定有迭代,但是迭代中不一定有递归,大部分可以相互转换
4、分治法:分治法是一种算法思想,分治法主要解决的问题是将大问题,进行拆分,拆分成若干个小的问题进行求解,最终将每个小问题的解进行合并。其实,分治法就是一种暴力破解法(穷举),也是一种搜索最优答案的算法。
5.递归和迭代的利弊
1.能用迭代的不用递归,递归调用函数,浪费空间,并且递归太深容易造成堆栈的溢出。
2.递归就是函数在进栈,进栈的次数多了,势必会占内存,无法避免的。在某些问题上,递归所写的代码要比迭代写的代码少。在某些问题上,迭代是写不出来的,所以只能用递归。
6.递归的处理方法;先递,后归。
1 前进段:指的是将大的问题进行小化
2 结束段:问题无法再继续化小,则处理当前的问题。
3 返回段:江晓的问题处理完毕后,向上返回(有些问题是不需要返回的)
注意:写递归一定要写他的end!
class Text01{
public static void main(String[] args){
show();
}
public static void show(){
System.out.println("show")
show();
}
}
上面是一个递归;函数show不停的在进行自身调用,因为在递归中并没有设置递归出口,所以只是不停的打印show这个字符串
7.练习去看递归和迭代计算1+2+3+…+98+99+100:
1.如果我们用迭代,我们需要运用for循环,并且需要一个数来记录下来:
class Text02{
public static void main(String[] args){int sum=0;
for(int i=1;i<=100;i++){
sum+=i;
}
System.out.println(sum);
}
}
2.如果我们要用递归来作我们需要把1加到100分为一个个小问题来记录。
f(n) 是求1~n的累加
f(100)就是我们当前最大的问题
写递归时,一定要先写它的end!
↓ 递
f(n)=f(n-1)+n
f(100)=f(99)+100 return 1+2+3+..+99 +100
f(99)=f(98)+99 return 1+2+...+98 +99
...
f(4)=f(3)+4 return 1+2+3+4
f(3)=f(2)+3 return 1+2+3
f(2)=f(1)+2 return 1+2
f(1)=1 return 1
→ end ↑ 归
那么此时递归的代码应该是
class Text03{
public static void main(String[] args){System.out.println(f(100));
}
public static int f(int n){
if(n==1){
return 1;
}
return f(n-1)+n;
}
}
斐波那契数列
1.定义:斐波那契数列(Fibonacci sequence),又称黄金分割数列、因数学家列昂纳多·斐波那契(Leonardoda Fibonacci)以兔子繁殖为例子而引入,故又称为“兔子数列”,指的是这样一个数列:1、1、2、3、5、8、13、21、34、这个数列从第3项开始,每一项都等于前两项之和。
import java.util.Scanner;
class Text04{
public static void main(String[] args){
Scanner s=new Scanner(System.in);
System.out.print("请输入一个数");
int n=s.nextInt();
for(int i=1;i<=n;i++){
System.out.println(fibo(i));
}
}
public static int fibo(int n){
if(n==1||n==2){
return 1;
}
return fibo(n-1)+fibo(n-2);
}
}
汉诺塔
问题介绍:汉诺塔:汉诺塔(又称河内塔)问题是源于印度一个古老传说的益智玩具。大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一个圆盘。
(图源于百度)从左至右依次为 X Z Y 注:在过程中的end是变化的
最大的问题将X上的三个盘子放到Z上
3个 X->Z 1. 目标是X全部到Z上
前2个 X->Y 1.1 将前两个放到中间的Y上,end是Y 借助Z
前1个 X->Z
第2个 X->Y
前1个 Z->Y
第3个 X->Z 1.2 将最大的放到Z上,end是Z,直接过去
前2个 Y->Z 1.3 把Y上的全部放到Z上,借助X
前1个 Y->X
第2个 Y->Z
前1个 X->Z
同理可得那64个同理得:
64个 X->Z
前63个 X->Y
前62个 X->Z
第63个 X->Y
前62个 Z->Y
第64个 X->Z
前63个 Y->Z
前62个 Y->X
第63个 Y->Z
前62个 X->Z
class Hanno{
public static void main(String[] args){
//盘子的个数 出发 中间 目的
hanno(64,"X","Y","Z");
}
public static void hanno(int n,String begin,String mid,String end){
if(n==1){
System.out.println(begin+" -> "+end);
}else{
hanno(n-1,begin,end,mid);
System.out.println(begin+" -> "+end);
hanno(n-1,mid,begin,end);
}
}
}