用栈来解决汉诺塔问题

这是一道比较比较复杂的问题,完全写下来会非常浪费时间,具体分析过程参见《程序员代码面试指南》。后面如果我有时间,就补充一下。

思路一:递归

import java.util.Scanner;
public class Main{
    public static int hanoiProblem(int num){
        if (num < 1) {
            return 0;
        }
        String left = "left";
        String mid = "mid";
        String right = "right";
        return process(num, left, mid, right, left, right);
    }
    public static int process(int num, String left, String mid, String right, String from, String to){
        if (num == 1) {
            if (from.equals("mid") || to.equals("mid")) {
                System.out.println("Move 1 from " + from + " to " + mid);
                return 1;
            } else {
                System.out.println("Move 1 from " + from + " to " + mid);
                System.out.println("Move 1 from " + mid + " to " + to);
                return 2;
            }
        }
        if (from.equals("mid") || to.equals("mid")){
            String another = (from.equals("left") || from.equals("left")) ? "right" : "left";
            int part1 = process(num - 1, left, mid, right, from, another);
            int part2 = 1;
            System.out.println("Move " + num + " from " + from + " to " + to);
            int part3 = process(num - 1, left, mid, right, another, to);
            return part1 + part2 + part3;
        } else {
            int part1 = process(num - 1, left, mid, right, from, to);
            int part2 = 1;
            System.out.println("Move " + num + " from " + from + " to " + mid);
            int part3 = process(num - 1, left, mid, right, to, from);
            int part4 = 1;
            System.out.println("Move " + num + " from " + mid + " to " + to);
            int part5 = process(num - 1, left, mid, right, from, to);
            return part1 + part2 + part3 + part4 + part5;
        }
    }
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        int num = sc.nextInt();
        int count = hanoiProblem(num);
        System.out.println("It will move " + count + " steps.");
    }
}

思路二:利用栈来实现

import java.util.Scanner;
import java.util.Stack;

enum Action {
    No, LtoM, MtoL, RtoM, MtoR
}

public class Main {
    public static int hanoiProblem2(int num) {

        String left = "left";
        String right = "right";
        String mid = "mid";
        Action[] record = {Action.No};
        int step = 0;

        Stack<Integer> lS = new Stack<>();
        Stack<Integer> mS = new Stack<>();
        Stack<Integer> rS = new Stack<>();

        lS.push(Integer.MAX_VALUE);
        mS.push(Integer.MAX_VALUE);
        rS.push(Integer.MAX_VALUE);

        for (int i = num; i > 0; i--) {
            lS.push(i);
        }

        while (rS.size() != num + 1) {
            step += fStackTotStack(record, Action.MtoL, Action.LtoM, lS, mS, left, mid);
            step += fStackTotStack(record, Action.LtoM, Action.MtoL, mS, lS, mid, left);
            step += fStackTotStack(record, Action.RtoM, Action.MtoR, mS, rS, mid, right);
            step += fStackTotStack(record, Action.MtoR, Action.RtoM, rS, mS, right, mid);
        }

        return step;
    }

    public static int fStackTotStack(Action[] record, Action preNoAct, Action nowAct,
                                     Stack<Integer> fStack, Stack<Integer> tStack, 
                                     String from, String to) {
                                     
        if (preNoAct != record[0] && fStack.peek() < tStack.peek()) {
            tStack.push(fStack.pop());
            System.out.println("Move " + tStack.peek() + " from " + from + " to " + to);
            record[0] = nowAct;
            return 1;
        }
        return 0;
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int num = sc.nextInt();
        int step = hanoiProblem2(num);
        System.out.println("It will move " + step + " steps.");
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值