zoukankan      html  css  js  c++  java
  • 实现单栈实现支持getMin的栈

    双栈实现getMin功能的问题

      左程云的《程序员代码面试指南》,第一个题是“设计一个有getMin功能”的栈,思路如下:

    用到了双栈:

    一个栈(stackData)用来保存当前栈中的元素,其功能和正常的栈没有区别;

    另外一个栈(stackMin)用来保存每一步的最小值;

      2种方案思路就是下面这幅图所示:

      

      

      如果使用上面图中的数据,其实发现不了什么问题,但是可以进行如下操作:

    getMin(); // 返回1
     // 直接从stackMin中获取栈顶元素,就是栈的最小值(1),正确
    
    pop();
    // stackData弹出1,同时stackMin中的栈顶元素所有1,然后stackMin栈顶元素为3,无异常
    
    top(); // 返回2
    // 从stackData获取栈顶元素(不出栈)
    
    getMin(); // 返回3
    // 从stackMin返回栈顶元素,但是返回的是3,而不是2,因为stackData的最小元素是2
    

      所以,书中的方案,并不能实现正确getMin功能,另外,如果换一组数据:0、1、0,画出的图如下:

        

      对于是上面的两个图,进行如下操作:

    getMin(); // 返回0  正确
    
    top();  // 返回0 正确
    
    pop(); // stackData的栈顶元素0出栈,同时,stackMin的所有元素都会出栈
    // 因为stackMin栈顶元素始终和stackData出站的元素相同,都为0
    
    top();  // 返回1 正确
    
    getMin(); // 出现异常,因为stackMin已经是个空栈了
    // 预期是返回0,因为stackData的栈底元素是0,比top元素小
    

      其实对于上面这个问题,也可以这样修改:

      1.stackData仍旧保持不变;

      2.stackMin中不是只存一个int,而是存一个Item;

      3.Item有两个域,一个data域,表示本次push的值,另一个是min,表示push当前这个值后,stackData的最小值。

      原理如如下所示:

      

      其实,看了上面这个双栈,你会发现,stackData是多余的,因为stackMin中已经包含了所有需要的数据,stackData完全没有存在的必要,所以建议使用单栈来实现,不要使用双栈了,不仅麻烦,而且还多费一些空间;

    单栈实现getMin功能

      使用单栈也比较简单,原理如下所示:

      

      Java实现代码如下:

    package cn.ganlixin.ds;
    
    
    import java.util.Stack;
    
    class Item {
        // 每次push的值
        int data;
    
        // data入栈后,栈的最小值
        int min;
    
        public Item(int data, int min) {
            this.data = data;
            this.min = min;
        }
    }
    
    public class MinStack {
    
        //存放元素的栈
        private Stack<Item> stack = null;
    
        public MinStack() {
            stack = new Stack<>();
    
        }
    
        public void push(int x) {
            // 栈为空,则push进来的x就是最小值
            if (stack.isEmpty()) {
                stack.push(new Item(x, x));
            } else {
    
                // 获取栈顶元素,因为栈顶元素的min保存了push x之前的最小值
                Item top = stack.peek();
    
                // 如果栈顶元素的最小值比当前x要小,则新Item的min为top.min
                stack.push(new Item(x, top.min > x ? x : top.min));
            }
        }
    
        public void pop() {
            stack.pop();
        }
    
        public int top() {
            return stack.peek().data;
        }
    
        public int getMin() {
            return stack.peek().min;
        }
    }
    

      

      测试:

    public class TestMinStack {
    
        @Test
        public void test() {
            MinStack minStack = new MinStack();
            minStack.push(0);
            minStack.push(1);
            minStack.push(0);
    
            System.out.println(minStack.getMin());  // 0
    
            minStack.pop();
            System.out.println(minStack.top());     // 1
    
            System.out.println(minStack.getMin());  // 0
        }
    }
    

      

  • 相关阅读:
    48. 旋转图像(顺时针)
    560. 和为K的子数组
    75. 颜色分类(三指针移动||计数排序)
    670. 最大交换
    常见端口号汇总
    springboot解决跨域问题跨域
    jad使用
    tomcat9:解决tomcat catalina log和localhost log中文乱码
    JUC:阻塞队列
    JUC:读写锁
  • 原文地址:https://www.cnblogs.com/-beyond/p/13227736.html
Copyright © 2011-2022 走看看