zoukankan      html  css  js  c++  java
  • 读书笔记之《程序员代码面试指南(栈和队列)》

    第一章、栈和队列

    有getMin功能的栈

    使用两个栈,一个用来保存当前栈中的元素,记为stackData,一个用来保存每一步的最小值,即为stackMin.

    public class MyStack {
        public static void main (String [] args){
            int [] Arr = {1,2,3};
            push(Arr[0]);
            push(Arr[1]);
            System.out.println(pop()+"  " + getMin());
        }
        private static Stack<Integer > stackData=new Stack<Integer>();
        private static Stack <Integer> stackMin =new Stack<Integer>();
    
        public static void push(int newNum){
            stackData.push(newNum);
            if(stackMin.isEmpty()){
                stackMin.push(newNum);
            }else if(newNum<stackMin.peek()){
                stackMin.push(newNum);
            }
        }
    
        public static int  pop(){
            if(stackData.peek()==stackMin.peek()){
                stackMin.pop();
            }
            return stackData.pop();
        }
    
        public static int getMin(){
            if(stackMin.isEmpty()){
                throw new RuntimeException("you stack is empty.");
            }
            return stackMin.peek();
        }
    }
    

    由两个栈组成的队列

    • 一个栈stackPush专门用来存数据
    • 一个栈stackPop专门用来取数据
    • 每次取数据前stackPop必须清空
    • 每次stackPush压入数据到stackPop中时,必须一次性全部压入
    public class MyStack {
        private static Stack<Integer > stackPush =new Stack<Integer>();
        private static Stack <Integer> stackPop  =new Stack<Integer>();
    
        public static void  add(int pushInt){
            stackPush.push(pushInt);
        }
    
        public static int poll(){
            if(stackPush.isEmpty()&&stackPop.isEmpty()){
                throw new RuntimeException("Queue is Empty !");
            }else if(stackPop.isEmpty()){
                while (!stackPush.isEmpty()){
                    stackPop.push(stackPush.pop());
                }
            }
            return stackPop.pop();
        }
    
        public static int peek(){
            if(stackPush.isEmpty()&&stackPop.isEmpty()){
                throw new RuntimeException("Queue is Empty !");
            }else if(stackPop.isEmpty()){
                while (!stackPush.isEmpty()){
                    stackPop.push(stackPush.pop());
                }
            }
            return stackPop.peek();
        }
    }
    

    用栈解决汉诺塔问题

    修改后的汉诺塔问题不能从左直接到右,也不能从右直接到左,必须通过中间;

    左、中、右三个地点依次记为LS,LM,RS;

    则仅有四个动作:LS-->LM 、LM-->LS 、LM-->RS 、RS-->LM

    动作:某一个栈(from)把栈顶元素弹出 ,然后压入到另一个栈里(to),作为这一个栈(to)的栈顶。

    两个原则:

    • 一个动作能发生的先决条件是不违反小压大的原则。
    • 还一个是相邻不可逆原则。

    意思是,L->M ,那么M->L,就重复了,如果要最小步法完成,必须不走重复步。

    核心

    • 游戏的第一个动作一定是L->M
    • 在走出任何最小步数过程中,四个动作,只有一个动作不违反原则,其余三个一定会违反。
    public class MyStack {
        public enum Action {
            No , LToM , MToL , MToR , RToM
        }
    
        public static  int hannoProblem(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<Integer>();
            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+= 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(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;
        }
      
        public static void main (String [] args){
            int num=2;
            String left="left";
            String mid ="mid";
            String right= "right";
            System.out.println(hannoProblem(num,left,mid,right));
        }
    }
    


    Learn ,Practice ,Summary !
  • 相关阅读:
    Java数据类型转换(自动转换和强制转换)
    Java数据类型以及变量的定义
    Java8新特性_日期时间新类 LocalDate、LocalTime、LocalDateTime
    Java8新特性_接口中的默认方法
    java8 新特性 Optional容器类
    Java8新特性 并行流与串行流 Fork Join
    Java8新特性_stream API 练习
    IDEA导入JUnit4
    Reduce:规约;Collector:收集、判断性终止函数、组函数、分组、分区
    【Linux】排序命令sort
  • 原文地址:https://www.cnblogs.com/daminzhou/p/8387108.html
Copyright © 2011-2022 走看看