天天看点

程序员代码面试指南刷题--第一章.用栈来求解汉诺塔问题

题目描述

汉诺塔问题比较经典,这里修改一下游戏规则:现在限制不能从最左侧的塔直接移动到最右侧,也不能从最右侧直接移动到最左侧,而是必须经过中间。求当塔有n层的时候,打印最优移动过程和最优移动总步数。

输入描述:

输入一个数n,表示塔层数

输出描述:

按样例格式输出最优移动过程和最优移动总步数

示例1
输入

2

输出

Move 1 from left to mid
Move 1 from mid to right
Move 2 from left to mid
Move 1 from right to mid
Move 1 from mid to left
Move 2 from mid to right
Move 1 from left to mid
Move 1 from mid to right
It will move 8 steps.
           

说明

解法一:递归

import java.io.*;
import java.util.*;
public class Main{
    public static void main(String[] args) throws Exception{
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int num = Integer.parseInt(br.readLine().trim());
        int res = H(num,"left","right","mid");
        System.out.println("It will move "+res+" steps.");
    }
    public static int H(int n,String from,String to,String mid){
        if(n==1){
            if(from.equals("mid")||to.equals("mid")){
                System.out.println("Move 1 from "+from+" to "+to);
                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")){
            int p1 = H(n-1,from,mid,to);
            System.out.println("Move "+n+" from "+from+" to "+to);
            int p2 = H(n-1,mid,to,from);
            return p1+1+p2;
        }else{
            int p1 = H(n-1,from,to,mid);
            System.out.println("Move "+n+" from "+from+" to "+mid);
            int p2 = H(n-1,to,from,mid);
            System.out.println("Move "+n+" from "+mid+" to "+to);
            int p3 = H(n-1,from,to,mid);
            return p1+p2+p3+2;
        }
    }
}
           

解法二:非递归

import java.io.*;
import java.util.*;
public class Main{
    public static Action record = Action.no;
    public static void main(String[] args) throws Exception{
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int num = Integer.parseInt(br.readLine().trim());
        int res = H(num,"left","right","mid");
        System.out.println("It will move "+res+" steps.");
    }
    public static int H(int n,String left,String right,String mid){
        Stack<Integer> l = new Stack<>();
        Stack<Integer> m = new Stack<>();
        Stack<Integer> r = new Stack<>();
        l.push(Integer.MAX_VALUE);
        m.push(Integer.MAX_VALUE);
        r.push(Integer.MAX_VALUE);
        for(int i=n;i>0;i--){
            l.push(i);
        }
        int step = 0;
        while(r.size()!=n+1){
            //只有一个能执行
            step += fsTots(Action.mtr,Action.rtm,r,m,right,mid);
            step += fsTots(Action.rtm,Action.mtr,m,r,mid,right);
            step += fsTots(Action.mtl,Action.ltm,l,m,left,mid);
            step += fsTots(Action.ltm,Action.mtl,m,l,mid,left);
        }
        return step;
    }
    public static int fsTots(Action preno,Action now,Stack<Integer> fs,Stack<Integer> ts,String from,String to){
        if(record!=preno&&fs.peek()<ts.peek()){
            record = now;
            ts.push(fs.pop());
            System.out.println("Move "+ts.peek()+" from "+from+" to "+to);
            return 1;
        }    
        return 0;
    }
    enum Action{
        no,ltm,mtl,rtm,mtr
    }
}