从o开始刷题(5) - 非递归、使用栈实现汉诺塔

233 阅读2分钟

[程序源代码面试指南第二版] 用栈来实现汉诺塔问题

描述

汉诺塔(非递归)

需求

不能直接从左到右或者从右到左,必须经过中间

咳咳

主要两个原则:

  1. 不能违反小压大原则 -from栈弹出的num压入to栈中,num必须小于当前to栈的栈顶
  2. 相邻不可逆原则 2.1. 上一步是L->M 根据小压大原则,L->M动作不会重复发生 根据相邻不可逆原则,M->L动作不会发生 根据小压大原则,R->M,M->R只有一个会达标

2.2. 上一步是M->L 根据小压大原则,M->L动作不会重复发生 根据相邻不可逆原则,L->M动作不会发生 根据小压大原则,R->M,M->R只有一个会达标

2.3. 上一步是R->M 根据小压大原则,R->M动作不会重复发生 根据相邻不可逆原则,M->R动作不会发生 根据小压大原则,L->M,M->L只有一个会达标

2.4. 上一步是M->R 根据小压大原则,M->R动作不会重复发生 根据相邻不可逆原则,R->M动作不会发生 根据小压大原则,L->M,M->L只有一个会达标

实际一共4个动作:

  1. 左->中
  2. 中->左
  3. 中->右
  4. 右->中

可以把中左右抽象成栈

  1. 左lS
  2. 中mS
  3. 右rS

初始化如果没值判断的时候要考虑栈空比较繁琐,因此压入最大值?只需要在循环时考虑到

附件

public static int haonoi(int num,String left,String mid,String right){
        Stack<Integer> lS = new Stack<Integer>();
        Stack<Integer> mS = new Stack<Integer>();
        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);
        }
        Action[ ] record = {Action.No};
        int step = 0;
        while(rS.size()!=num + 1){
            step += fStackToStack(record,Action.ML,Action.LM,lS,mS,left,mid);
            step += fStackToStack(record,Action.LM,Action.ML,mS,lS,mid,left);
            step += fStackToStack(record,Action.RM,Action.MR,mS,rS,mid,right);
            step += fStackToStack(record,Action.MR,Action.RM,rS,mS,right,mid);
        }
        return step;
    }

    private   static int fStackToStack(Action[] record, Action preNoAct, Action nowAct, Stack<Integer> fStack, Stack<Integer> tStack, String from, String to) {
        if(record[0] != preNoAct && 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;
    }
}
enum Action{
    No,
    LM,
    ML,
    MR,
    RM
}

。。完全糟糕,我太弱了