• 《程序员代码面试指南》第一章 栈和队列 用栈实现汉诺塔问题


    用栈实现汉诺塔,不能直接从左移到右,或者从右移到左,必须经过中间柱子。

    java代码

    
    /**
     * @Description:用栈来实现汉诺塔
     * @Author: lizhouwei
     * @CreateDate: 2018/4/5 17:30
     * @Modify by:
     * @ModifyDate:
     */
    public class Chapter1_6 {
        public static final String LEFT = "left";
        public static final String MID = "mid";
        public static final String RIGHT = "right";
    
        public int recMoveHanoi(int n, String left, String mid, String right) {
            if (n < 1) {
                return 0;
            }
            return recMoveHanoi(n, left, mid, right, LEFT, RIGHT);
        }
    
        //递归实现
        public int recMoveHanoi(int n, String left, String mid, String right, String from, String to) {
            //递归的终止条件 n==1
            if (n == 1) {
                //从左或右 移动到中间的,或者从中间移动到左或者右的,都只要一步
                if (MID.equalsIgnoreCase(from) || MID.equalsIgnoreCase(to)) {
                    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 (MID.equalsIgnoreCase(from) || MID.equalsIgnoreCase(to)) {
                //获取对应的作为辅助的柱子,例如 from为mid ,to为left,则 right为辅助的柱子,
                String another = LEFT.equalsIgnoreCase(to) || LEFT.equalsIgnoreCase(from) ? RIGHT : LEFT;
                int step1 = recMoveHanoi(n - 1, left, mid, right, from, another);
                int step2 = 1;
                System.out.println("move " + n + " from " + from + " to " + to);
                int step3 = recMoveHanoi(n - 1, left, mid, right, another, to);
                return step1 + step2 + step3;
            } else {
                //从左到右 或者 从右到左
                //1.此时 n在form上,要经过mid,才能到to ,所以先将to作为辅助,将 n-1 移到to上
                int step1 = recMoveHanoi(n - 1, left, mid, right, from, to);
                //2.此时 n在form上, n-1在to上,所以将n移到mid上
                int step2 = 1;
                System.out.println("move " + n + " from " + from + " to  mid");
                //3.此时 n-1在to上,n在mid上,from作为辅助 ,所以先将n-1移到from上
                int step3 = recMoveHanoi(n - 1, left, mid, right, to, from);
                //4.此时 n-1在from上,n在mid上,将n移到to上
                int step4 = 1;
                System.out.println("move " + n + " from  mid to " + to);
                //5.此时 n-1在from上,n在to上,所以先将n-1移到to上
                int step5 = recMoveHanoi(n - 1, left, mid, right, from, to);
                return step1 + step2 + step3 + step4 + step5;
            }
        }
    //---------------------------------------------------------------------------------------------------//
    
        //用有序的栈来实现,充分运用了有序的特性,和同一动作不能连续重复和可逆
        public int moveHanoi(int n, String left, String mid, String right) {
            Stack<Integer> leftStack = new Stack<Integer>();
            Stack<Integer> midStack = new Stack<Integer>();
            Stack<Integer> rightStack = new Stack<Integer>();
            leftStack.push(Integer.MAX_VALUE);
            midStack.push(Integer.MAX_VALUE);
            rightStack.push(Integer.MAX_VALUE);
            //初始化左边的柱子上的元素
            for (int i = n; i > 0; i--) {
                leftStack.push(i);
            }
            int step = 0;
            //定义上一步的动作,默认为NO
            Action[] action = {Action.NO};
            while (rightStack.size() != n + 1) {
                step += moveHanoi(action, Action.ML, Action.LM, leftStack, midStack, LEFT, MID);
                step += moveHanoi(action, Action.LM, Action.ML, midStack, leftStack, MID, LEFT);
                step += moveHanoi(action, Action.RM, Action.MR, midStack, rightStack, MID, RIGHT);
                step += moveHanoi(action, Action.MR, Action.RM, rightStack, midStack, RIGHT, MID);
            }
            return step;
        }
    
        public int moveHanoi(Action[] action, Action preAction, Action curAction, Stack<Integer> fromStack, Stack<Integer> toStack, String from, String to) {
            if (action[0] != preAction && fromStack.peek() < toStack.peek()) {
                toStack.push(fromStack.pop());
                System.out.println("move " + toStack.peek() + " from " + from + " to " + to);
                action[0] = curAction;
                return 1;
            }
            return 0;
        }
    
        //测试
        public static void main(String[] args) {
            Chapter1_6 chapter = new Chapter1_6();
            //递归
            // System.out.println("step sum "+chapter.recMoveHanoi(4,LEFT,MID,RIGHT));
            System.out.println("=====================");
            //非递归
            System.out.println("step sum " + chapter.moveHanoi(4, LEFT, MID, RIGHT));
        }
    }
    
    //定义 移动的动作
    enum Action {
        NO, LM, ML, MR, RM;
    }
    
  • 相关阅读:
    jmeter中设置线程数与设置集合点的区别
    在linux系统中如何通过shell脚本批量设置redis键值对
    服务器带宽上行与下行的区别
    性能测试之Jmeter插件安装
    sqlserver 启用邮箱服务
    sqlserver 自定义字符串分割函数.
    C# 重写思想
    CSS控制鼠标滑过时的效果
    js实现图片自动切换效果。
    SQL Server Management Studio 使用作业实现数据库备份
  • 原文地址:https://www.cnblogs.com/lizhouwei/p/8724128.html
Copyright © 2020-2023  润新知