1、基本概念
递归(英语:Recursion),在数学和计算机科学中是指在函数的定义中使用函数自身的方法,在计算机科学中还额外指一种通过重复将问题分解为同类的子问题而解决问题的方法。
递归代码最重要的两个特征:结束条件和自我调用。自我调用是在解决子问题,而结束条件定义了最简子问题的答案。
int func(传入数值) {
if (终止条件) return 最小子问题解;
return func(缩小规模);
}
2、递归执行机制
3、斐波那契数列
斐波那契数列是指这样一个数列:1,1,2,3,5,8,13,21,34,55,89……这个数列从第3项开始 ,每一项都等于前两项之和。
递归求斐波那契数列
边界条件第一个数和第二个数,都为1
java 实现
class Way{
public int fibonacci(int n){
if(n >= 1){
if(n == 1)
return 1;
if(n == 2)
return 1;
else{
return fibonacci(n-1) + fibonacci(n-2);
}
}else{
System.out.println("输入的数字不合法");
return 0;
}
}
}
信息学奥赛一本通 1201:菲波那契数列
c++实现
#include<iostream>
using namespace std;
int fibonacci(int n){
if(n == 1 || n == 2) return 1;
else{
return fibonacci(n-1) + fibonacci(n-2);
}
}
int main(){
int k;
cin >> k;
while(k--){
int n;
cin >> n;
cout <<fibonacci(n) << endl;
}
return 0;
}
4、猴子吃桃
有一堆桃,一个猴子每天吃这堆桃的一半再多吃一个,到第10天还剩一个桃子
思路 第十天有一个桃子,第九天有 (1+1)*2 = 4个桃子, 第八天有 (4+1)*2 = 10个桃子,
第七天有 (10+1)*2 = 22 个桃子……
class Ways{
public int peach(int days){
if(days == 10){
return 1;
}else if(days <= 9 && days >= 1){
return 2*(peach(days+1)+1);
}else{
System.out.println("day在1~10之间");
return -1;
}
}
}
5、老鼠出迷宫
public class MiGong{
public static void main(String[] args){
//创建迷宫 8*7 0表示可以走, 1表示障碍物
int[][] map = new int[8][7];
//将最上面一行和最下面一行全置1
for(int i = 0; i < 7; i++){
map[0][i] = 1;
map[7][i] = 1;
}
//将最右面一列和最左边一列全置1
for(int i = 0; i < 8; i++){
map[i][0] = 1;
map[i][6] = 1;
}
map[3][1] = 1;
map[3][2] = 1;
//输出当前地图
System.out.println("=====地图为======");
for(int i = 0; i < map.length; i++){
for(int j = 0; j < map[i].length; j++){
System.out.print(map[i][j] + " ");
}
System.out.println();
}
//路线
Solution s = new Solution();
s.findWay(map,1,1);
System.out.println("=====路线为======");
for(int i = 0; i < map.length; i++){
for(int j = 0; j < map[i].length; j++){
System.out.print(map[i][j] + " ");
}
System.out.println();
}
}
}
class Solution{
//i,j为老鼠位置初始为(1,1)
//0表示可以走
//1表示障碍物
//2表示走出迷宫的路线
//3表示死路
//当map[6][5] = 2说明找到通路可以结束
public boolean findWay(int[][] map, int i, int j){
if(map[6][5] == 2){
return true;
}else{
if(map[i][j] == 0){
map[i][j] = 2;
if(findWay(map,i+1,j)) return true;
else if(findWay(map,i,j+1)) return true;
else if(findWay(map,i-1,j)) return true;
else if(findWay(map,i,j-1)) return true;
else{
map[i][j] = 3;
return false;
}
}else{
return false;
}
}
}
}
6、汉诺塔
汉诺塔问题是一个经典的问题。汉诺塔(Hanoi Tower),又称河内塔,源于印度一个古老传说。大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,任何时候,在小圆盘上都不能放大圆盘,且在三根柱子之间一次只能移动一个圆盘。问应该如何操作?
java实现
class Tower{
//num 表示要移动的个数 a,b,c分别表示A塔、B塔、C塔;
//将A塔的所有盘子移动到C塔
public void move(int num, char a, char b, char c){
if(num == 1){
System.out.println(a + "->" + c);
}else {
//若有多个盘子 可以看成两个 最下面和上面的所有盘
//先移动上面所有的盘到b,借助c
move(num-1,a,c,b);
//把最下面的盘子移到c
System.out.println(a + "->" + c);
//再把b塔所有盘移到c 借助a
move(num-1,b,a,c);
}
}
}
信息学奥赛一本通 1205:汉诺塔问题
c++实现
//输出用cout 会超时!!!
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
void hanoitower(int n, char a, char b, char c){
if(n == 1) printf("%c->%d->%c\n",a,n,c);
else{
hanoitower(n-1,a,c,b);
printf("%c->%d->%c\n",a,n,c);
hanoitower(n-1,b,a,c);
}
}
int main(){
int n;
char op1, op2, op3;
cin >> n >> op1 >> op2 >> op3;
hanoitower(n,op1,op3,op2);
return 0;
}