递归设计的核心
递归设计的核心在于两点:
- 递归停止条件的判断
- 递归中对于问题的普适情况的解决方案
抓住这两点才能巧妙的解决问题。
递归问题的经典案例:
- 迷宫问题
- 汉诺塔问题
迷宫问题
假设有如下迷宫,其中1代表通路,0代表短路,请找出走出迷宫的道路。
1110110001111
1011101111001
0000101010100
1110111010111
1010000111001
1011111101111
1000000000000
1111111111111
解决问题的思路:
终止条件:
如果所在格子是迷宫的最右下角,且该格子数值为1,那么迷宫走通,递归结束。递归内容
如果所在格子是迷宫的第m行,第n列,则进行如下判断
a. 如果该格子是在迷宫矩阵中,且数值为1,那么我们将齐标记为以判定格子(改写数值为3)
b. 然后分别判断该格子的上下左右相邻格子是否为通路
c. 如果相邻格子中有一个递归判断是通路,则当前格子在走出迷宫的道路上(改写数值为7)
d. 向上层返回对格子是否在通路上的判断
代码展示
Maze.java
package recurrence.maze;
public class Maze {
public static int UNBLOCKED = 1;
public static int TRIED = 3;
public static int PATH = 7;
public static int[][] MAZE = { { 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 } };
public static boolean traverse(int row, int column) {
boolean isValidPath = false;
if (valid(row, column)) {
MAZE[row][column] = TRIED;
if (row == MAZE.length - 1 && column == MAZE[0].length - 1) {
isValidPath = true;
} else {
isValidPath = traverse(row + 1, column); // down
if (!isValidPath) {
isValidPath = traverse(row, column + 1); // right
}
if (!isValidPath) {
isValidPath = traverse(row - 1, column); // up
}
if (!isValidPath) {
isValidPath = traverse(row, column - 1); // left
}
}
if (isValidPath) {
MAZE[row][column] = PATH;
}
}
return isValidPath;
}
public static boolean valid(int row, int column) {
boolean result = false;
if (row >= 0 && row < MAZE.length && column >= 0 && column < MAZE[row].length) {
if (MAZE[row][column] == UNBLOCKED) {
result = true;
}
}
return result;
}
public static void printMaze() {
for (int[] row : Maze.MAZE) {
for (int column : row) {
System.out.print("" + column);
}
System.out.println();
}
}
}
MazeSearch.java
public class MazeSearch {
public static void main(String[] args) {
System.out.println("Before search");
Maze.printMaze();
if (Maze.traverse(0, 0)) {
System.out.println("\nThere is a path.\n");
} else {
System.out.println("\nNo valid path.\n");
}
System.out.println("After search");
Maze.printMaze();
}
}
最后结果
7770110001111
3077707771001
0000707070300
7770777070333
7070000773003
7077777703333
7000000000000
7777777777777
汉诺塔问题
汉诺塔问题所解决的问题模型是:
有三根柱子1柱子、2柱子和3柱子,n个盘子按照从小到大的顺序依次叠放在一根柱子上,要求在不能将大盘子放置在小盘子的规则下,将n个盘子移至另一个柱子上,从小到大按序叠放好。
解决思路:
- 递归停止的判断条件为将一个盘子从起点柱子直接移至终点柱子。
- 递归内容:如要完成n个盘子从起点柱子1移至终点柱子3需要
a. 将n-1个盘子从柱子1移至柱子2
b. 将最大的盘子从柱子1移至柱子3
c. 将n-1个盘子从柱子2移至柱子3
其中a,b又创造了新的移动问题,即移动n-1个盘子从某一起点柱至终点柱。
public class Hanoi {
public static void main(String[] args) {
int n = 4;
System.out.println("Begin to resolve Hanoi problem for [" + n + "] disks.");
Hanoi.hanoiMove(n, 1, 3, 2);
}
public static void hanoiMove(int n, int start, int end, int temp) {
if (n == 1) {
moveOneDisk(start, end);
} else {
hanoiMove(n - 1, start, temp, end);
moveOneDisk(start, end);
hanoiMove(n - 1, temp, end, start);
}
}
public static void moveOneDisk(int start, int end) {
System.out.println("Move disk from post [" + start + "] to post [" + end + "]");
}
}
输出结果
Begin to resolve Hanoi problem for [4] disks.
Move disk from post [1] to post [2]
Move disk from post [1] to post [3]
Move disk from post [2] to post [3]
Move disk from post [1] to post [2]
Move disk from post [3] to post [1]
Move disk from post [3] to post [2]
Move disk from post [1] to post [2]
Move disk from post [1] to post [3]
Move disk from post [2] to post [3]
Move disk from post [2] to post [1]
Move disk from post [3] to post [1]
Move disk from post [2] to post [3]
Move disk from post [1] to post [2]
Move disk from post [1] to post [3]
Move disk from post [2] to post [3]
本文探讨了递归设计的核心,包括停止条件和普适性解决方案,并通过迷宫问题和汉诺塔问题的具体案例,阐述了递归在解决问题中的应用。在迷宫问题中,通过设定终止条件和递归判断找到通路;在汉诺塔问题中,利用递归策略解决盘子的转移问题。

1553

被折叠的 条评论
为什么被折叠?



