递归
什么是递归? 直接或间接的调用自身的算法称为递归算法,打趣的来说 就是 “自己玩自己”。既然递归是一个反复调用自身的过程,这就说明它每一级的功能都是一样的,因此只需关注一级递归的解决过程即可。
从 bokeyuan博主 三年一梦的总结中,解递归题的三部曲:
1,找整个递归的终止条件:递归应该在什么时候结束?
2, 找返回值:应该给上一级返回什么信息?
3,本级递归应该做什么:在这一级递归中,应该完成什么任务?
迭代
迭代是利用变量的原值推算出变量的一个新值,如果递归是自己调用自己的话,迭代就是A不停的调用B。也就是,递归是自己玩自己,迭代是自己玩别人。
递归经典例题
例1: n的阶乘
package com.company;
import java.math.BigInteger;
import java.util.Scanner;
public class N_ {
public static void main(String[] args) {
System.out.println("求数字几的阶乘啊?");
Scanner a = new Scanner(System.in);
int b = a.nextInt();
System.out.println(ade(b));
}
public static long ade(long c) {
if (c <= 0) {
return 0;
} else if (c == 1) {
return 1;
} else return c * ade(c - 1);
}
}
对代码加入了scanner,可以获取任意数的阶乘,需要注意的是 int可表示范围, 在java中,int 最多到12的阶乘,long最多到20,BigInteger随意精度,运算符应用受限(暂时还不会用)。
例2:斐波纳切数列
package com.company;
import java.util.Scanner;
public class factorial {
public static void main(String[] args) {
System.out.println("请输入n:");
Scanner a = new Scanner(System.in);
String b = a.next();
int c = Integer.parseInt(b);
System.out.println(func(c));
}
public static int func(int n) {
if (n < 0) {
return 0;
} else if (n == 1) {
return 1;
} else {
return n * func(n - 1);
}
}
}
例3: 汉诺塔问题
(1) 最后盘子都放在B上
package com.company;
import java.util.Scanner;
public class Hnaoi{
static int times;
public static void main(String[] args) {
char A = 'A';
char B = 'B';
char C = 'C';
Scanner q = new Scanner(System.in);
System.out.println("请输入盘子数:");
int n = q.nextInt();
hno(n,A,B,C);
}
public static void move(int Disk, char M,char N){
System.out.println("第"+(++times)+"次移动,盘子" +Disk+" " +M +"到"+N);
}
public static void hno(int n,char A,char B,char C){
if( n == 1){
move(1,A,B);
}else {
hno(n-1,A,C,B);
move(n,A,B);
hno(n-1,C,B,A);
}
}
}
(2) 盘子全部放C上
public class Hnaoi {
static int times;
public static void main(String[] args) {
char A = 'A';
char B = 'C';
char C = 'B';
System.out.println("汉诺塔游戏开始!!");
System.out.println("请输入盘子数:");
Scanner s = new Scanner(System.in);
int n = s.nextInt();
hna(n,A,B,C);
}
public static void move(int disk,char M,char N){
System.out.println("第" +(++times)+ "次移动. 盘子" + disk +" "+ M+ "--->" +N);
}
public static void hna(int n,char A,char B,char C){
if (n == 1){
move(n,A,C);
}else {
//移动上一关的步骤到B
hna(n-1,A,C,B);
//吧最大盘子移动到C
move(n,A,C);
//再把c上上一关移动的盘子放到b上就可以了
hna(n-1,B,A,C); //B --C
}
}
}
例4: 搜索二叉树深度
public class BinaryTreeDepth {
ic static int getTreeDepth(Tree t) {
// 树为空
if (t == null) // 递归终止条件
return 0;
int left = getTreeDepth(t.left); // 递归求左子树深度,缩小问题的规模
int right = getTreeDepth(t.left); // 递归求右子树深度,缩小问题的规模
return left > right ? left + 1 : right + 1;
}
}
上述例题均为递归算法入门题,后续要在Leetcode多做几道递归题,加深理解。
leetcode.344.反转字符串(困难等级:简单)。
题目:编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 char[] 的形式给出。不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。你可以假设数组中的所有字符都是 ASCII 码表中的可打印字符。
public void res(char[] s) {
trs(s, 0, s.length-1);
}
public void trs(char[] s, int start, int end) {
if(start > end)
return;
trs(s, start+1, end-1);
char temp = s[start];
s[start] = s[end];
s[end] = temp;
}