递归指的是在方法内部对方法自身调用;递归一般用于一些常见的算法的解决,在实际应用中,
比如对文件夹内部文件的递归检索;以及树形菜单的显示;递归是对循环的一种补充 。
递归,就是在运行的过程中调用自己。
构成递归需具备的条件:
1. 子问题须与原始问题为同样的事,且更为简单;
2. 不能无限制地调用本身,须有个出口,化简为非递归状况处理。
经典的递归问题:
一、约瑟夫环
有100个人围成一个圈(编号0-99),从第0号的人开始从1报数,凡报到3的倍数的人离开圈子,然后再数下去,
直到最后只剩一个人为止,问此人原来的位置是多少号?
public static void main(String[] args) {
//声明布尔类型数组,用于标记这个人是否在圈中
boolean[] b = new boolean[100];
//初始化所有人都位于圈中(设置true)
for(int i = 0;i < b.length;i++){
b[i] = true;
}
//初始化圈中的总人数
int len = b.length;
//声明计数器,统计是否到达3
int count = 0;
//初始化索引,记录当前数到圈中的位置
int index = 0;
//开始循环报数
while(len > 1){
//判断当前位置的人是否在圈中
if(b[index]){
//计数器递增
count++;
//判断是否到达3
if(count == 3){
//人数减少
len--;
//标记此人离开圈子
b[index]=false;
//计数器归零
count = 0;
}
}
//数组索引递增
index++;
if(index == b.length){
index = 0;
}
}
//循环判断,数组中为true的元素的位置(即为剩下的人原来的位置)
for(int i = 0;i<b.length;i++){
if(b[i]){
System.out.println(i);
break;
}
}
}
李白打酒
话说大诗人李白,一生好饮。幸好他从不开车。
一天,他提着酒壶,从家里出来,酒壶中有酒2斗。他边走边唱:
无事街上走,提壶去打酒。
逢店加一倍,遇花喝一斗。
这一路上,他一共遇到店5次,遇到花10次,已知最后一次遇到的是花,他正好把酒喝光了。
请你计算李白遇到店和花的次序,可以把遇店记为a,遇花记为b。则:babaabbabbabbbb 就是合理的次序。
像这样的答案一共有多少呢?请你计算出所有可能方案的个数(包含题目给出的)。
public class LiBaiDaJiu {
//记录方法一共有多少个
static int count = 0;
// b为酒馆数量,f为花的数量,a为酒的量
public static int func(int b, int f, int a) {
//处理小酒馆数量、花的数量、酒的余量异常情况
if (b < 0 || f < 0 || a < 0) {
return 0;
}
// 最后一个遇见花并且把酒喝光
if (b == 0 && f == 1 && a == 1) {
count++;
return 1;
}
// 逢店加一倍 遇花喝1斗
return func(b - 1, f, 2 * a) + func(b, f - 1, a - 1);
}
public static void main(String[] args) {
//初始时店为5个,花为10个,酒为2斗
func(5,10,2);
System.out.println(count);
}
}
39级台阶
小明看完电影《第39级台阶》,离开电影院的时候,他数了数视觉的台阶数,恰好是39级。站在台阶前,
他突然又想起一个问题: 如果我每一步只能迈上1个或2个台阶,先迈左脚,然后左右交替,
最后一步迈右脚,也就是说一共要迈偶数步。那么上完39级台阶,有多少种不同的上法呢?
public class TaiJie {
static int count = 0;//上台阶的方法数量
//t为已经上的台阶数目 foot为上台阶时的步数
static void method(int t,int foot){
//处理步数异常的情况
if(t > 40){
return;
}
//台阶数为39,步数为偶数时上台阶的方法加一种
if(t == 39 && foot % 2 == 0){
count++;
return;
}
//一次上一个台阶
method(t+1,foot+1);
//一次上两个台阶
method(t+2,foot+1);
}
public static void main(String[] args) {
//初始状态是一个台阶也没有上,一步也没有走
method(0,0);
//输出上台阶方法的个数
System.out.println(count);
}
}
递归可以让复杂的问题变的简单,我们只需要给递归一个出口,它就可以帮我们把所有的可能性都计算出来,递归极大程度的减少了代码量,所以在理解的时候变得有点困难,但我们自己可以不用知道递归的内部具体是如何实现的,只需要知道该如何去用,递归是我们解决算法问题的好帮手!