递归设计

本文探讨了递归设计的核心,包括停止条件和普适性解决方案,并通过迷宫问题和汉诺塔问题的具体案例,阐述了递归在解决问题中的应用。在迷宫问题中,通过设定终止条件和递归判断找到通路;在汉诺塔问题中,利用递归策略解决盘子的转移问题。

递归设计的核心

递归设计的核心在于两点:

  1. 递归停止条件的判断
  2. 递归中对于问题的普适情况的解决方案

抓住这两点才能巧妙的解决问题。

递归问题的经典案例:

  1. 迷宫问题
  2. 汉诺塔问题

迷宫问题

假设有如下迷宫,其中1代表通路,0代表短路,请找出走出迷宫的道路。

1110110001111
1011101111001
0000101010100
1110111010111
1010000111001
1011111101111
1000000000000
1111111111111

解决问题的思路:

  1. 终止条件:
    如果所在格子是迷宫的最右下角,且该格子数值为1,那么迷宫走通,递归结束。

  2. 递归内容
    如果所在格子是迷宫的第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个盘子移至另一个柱子上,从小到大按序叠放好。

解决思路:

  1. 递归停止的判断条件为将一个盘子从起点柱子直接移至终点柱子。
  2. 递归内容:如要完成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]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值