基本概念
递归是一种程序设计技术,允许一个方法调用自己以达到最终目的。
递归与迭代
- 迭代是重复反馈过程的活动,其目的通常是为了逼近所需目标或结果。每一次对过程的重复称为一次“迭代”,而每一次迭代得到的结果会作为下一次迭代的初始值。即迭代过程的每一次结果,都是由对前一次所得结果施行相同的运算步骤得到的。
- 理论上递归和迭代可以相互转换。迭代一定可以转化为递归,递归不一定能转化为迭代。
- 实际应用中递归的算法要比迭代效率低,因为程序每调用一个函数,都要为其分配栈空间。但理论上,对于同一问题,递归和迭代的算法时间复杂度是相同的。
- 对于某些问题,递归是最精炼和适当的算法,但对于其他的问题,递归则不如迭代解法直观。
- 示例:计算1-N的和
递归实现
public int sum(int num) {
int result;
if(num == 1) {
result = 1;
}else {
result = num + sum(num-1);
}
return result;
}
迭代实现
public int sum(int num){
int result = 0;
for(int i=1; i<=num; i++){
result += i;
}
}
递归需要遵循的规则
- 当程序执行到一个方法时,就会开辟一个独立的空间(栈);
- 方法中的局部变量是独立的,不会相互影响;
- 如果使用的是引用类型变量(比如数组),就会共享该引用类型的数据。
- 递归必须向退出递归的条件逼近,否则就会无限递归;
- 当一个方法执行完毕,或者遇到return,就会返回,遵守谁调用,就将结果返回给谁。
递归解决迷宫问题
/**
* 代码来自 《Java程序设计教程(第七版)》,修改变量名是我最后的倔强
*
*/
public class MazeQuestion {
public static void main(String[] args) {
Maze m = new Maze();
System.out.println(m);
if(m.traverse(0, 0)) {
System.out.println("已找到迷宫路径。");
}else {
System.out.println("迷宫没有路径。");
}
System.out.println(m);
}
}
/**
* 迷宫类
* @author dxt
*
*/
class Maze{
//迷宫,入口为grid[0][0],出口为右下角元素,数字为1表示迷宫中的路,0表示墙
private int[][] grid = {{1,1,1,0,1,1,0,0,0,1,1,1,1},
{1,0,1,1,1,0,1,1,1,1,0,0,1},
{0,0,0,0,1,0,1,0,1,0,1,0,0},
{1,1,1,0,1,1,1,0,1,0,1,1,1},
{1,0,1,0,0,0,0,1,1,1,0,0,1},
{1,0,1,1,1,1,1,1,0,1,1,1,1},
{1,0,0,0,0,0,0,0,0,0,0,0,0},
{1,1,1,1,1,1,1,1,1,1,1,1,1}};
private final int PATH = 3; //走出迷宫的路径用数字3表示
private final int TRIED = 4; //走过的但不通的路用数字4表示
/**
* 使用递归去遍历整个迷宫,在遍历过程中将 路径 标示出来
* @param row
* @param col
* @return
*/
public boolean traverse(int row, int col) {
boolean done = false;
//先判断输入的 row 和 col 是否合法
if(valid(row, col)) { //如果合法
grid[row][col] = TRIED; //遍历此合法位置
if(row == grid.length-1 && col == grid[0].length-1) {
//遍历完毕(到了迷宫出口)
done = true;
}else {
done = traverse(row+1, col); //下移
if(!done) {
done = traverse(row, col+1); //右移
}
if(!done) {
done = traverse(row-1, col); //上移
}
if(!done) {
done = traverse(row, col-1); //左移
}
}
if(done) {
grid[row][col] = PATH;
}
}
return done;
}
//判断索引是否合法
public boolean valid(int row, int col) {
if(row >= 0 && row < grid.length && col >= 0 && col < grid[0].length) {
if(grid[row][col] == 1) {
return true;
}
}
return false;
}
//输出grid
public String toString() {
String result = "\n";
for(int i=0; i<grid.length; i++) {
for(int j=0; j<grid[0].length; j++) {
result += grid[i][j] + " ";
}
result += "\n";
}
return result;
}
}
结果