zoukankan      html  css  js  c++  java
  • 155. Min Stack

    题目:

    Design a stack that supports push, pop, top, and retrieving the minimum element in constant time.

    • push(x) -- Push element x onto stack.
    • pop() -- Removes the element on top of the stack.
    • top() -- Get the top element.
    • getMin() -- Retrieve the minimum element in the stack.

    链接: http://leetcode.com/problems/min-stack/

    题解:

    最小栈。这道题在电面Bloomberg的supply chain组的Senior SDE时遇到了原题,秒杀掉了。然后面试的老印很坏,follow up说你这个不是stack, 说想要new stack<>()的时候自带min功能,跟我绕了半天,故意误导, 好恶心...最后果然电面没过-_____-!! 后来看了CC150, 才知道这老印也许想要的是CC150的写法 - MinStack extends Stack<Integer>, 然后用minStack和super进行互动,也是两个栈。

    又聊远了,这道题目,保持stack的功能同时还要有getMin()。一般的方法是维护两个stack。 也可以维护一个stack,但要创建一个Node class,空间复杂度并不能被节省。 还有的做法是用一个stack,stack里存min到当前值x的距离,然后有些计算,比较巧妙。

    维护两个stack, Time Complexity (pop,push,getMin,top) - O(1) , Space Complexity - O(n)。

    class MinStack {
        private Stack<Integer> stack = new Stack<>();
        private Stack<Integer> minStack = new Stack<>();
        
        public void push(int x) {
            if(minStack.isEmpty() || x <= minStack.peek())
                minStack.push(x);
            stack.push(x);
        }
    
        public void pop() {
            if(stack.peek().equals(minStack.peek()))
                minStack.pop();
            stack.pop();
        }
    
        public int top() {
            return stack.peek();
        }
    
        public int getMin() {
            return minStack.peek();
        }
    }

    维护一个栈,  Time Complexity (pop,push,getMin,top) - O(1) , Space Complexity - O(n)。

    class MinStack {
        private Stack<Node> stack;
        
        public MinStack() {
            this.stack = new Stack<>();    
        }
        
        public void push(int x) {
            int min = Math.min(x, getMin());
            this.stack.push(new Node(x, min));
        }
    
        public void pop() {
            this.stack.pop();
        }
    
        public int top() {
            return this.stack.peek().val;
        }
    
        public int getMin() {
            if(this.stack.isEmpty())
                return Integer.MAX_VALUE;
            return this.stack.peek().min;
        }
        
        private class Node {
            public int min;
            public int val;
            
            public Node(int val, int min) {
                this.val = val;
                this.min = min;
            }
        }
    }

    二刷:

    除了维护两个栈的方法以外,还有两种方法, 一种是建立一个Node同时保存当前值和最小值。

    另外一种是reeclapple的写法。

    1. 设定一个min,push的时候,除了第一个数外,只把每个数x和min的差值(x - min)存入栈。当 x< min的时候更新min = x
    2. pop的时候pop出这个差值,假如这个值小于0,我们更新min = min - pop,否则min不变
    3. 计算peek的时候,先peek出栈顶元素, 假如这个元素top大于0,那么返回  top + min, 否则返回min。这里理解比较tricky.
    4. 计算getMin的时候直接返回min

    Java:

    最简单的维护两个stack的。

    class MinStack {
        private Stack<Integer> minStack = new Stack<>();
        private Stack<Integer> stack = new Stack<>();
        
        public void push(int x) {
            stack.push(x);
            if (minStack.isEmpty() || x <= minStack.peek()) {
                minStack.push(x);
            }
        }
    
        public void pop() {
            int x = stack.pop();
            if (x == minStack.peek()) {
                minStack.pop();
            }
        }
    
        public int top() {
            return stack.peek();
        }
    
        public int getMin() {
            return minStack.peek();
        }
    }

    三刷:

    要注意假如遇到的话,还要加上各种边界条件判断以及throw EmptyStackException

    Java:

    class MinStack {
        private Stack<Integer> stack = new Stack<>();
        private Stack<Integer> minStack = new Stack<>();
        
        public void push(int x) {
            stack.push(x);
            if (minStack.isEmpty() || x <= minStack.peek()) minStack.push(x);
        }
    
        public void pop() {
            int x = stack.pop();
            if (x == minStack.peek()) minStack.pop();
        }
    
        public int top() {
            return stack.peek();
        }
    
        public int getMin() {
            return minStack.peek();
        }
    }

    使用一个Stack: 

    每次min要被更新的时候,先存入min,再存入新元素。相当于保持一个递减的min序列。  假如elements递减,则栈内元素类似 {min 1, elem1, min2, elem2, min3, elem3}等等,

    1. 这里在insert的时候,假如x <= min,则我们先把之前被更新过的min放进stack里, 把min设为当前的x, 之后把x放入栈
    2. 在pop的时候, 我们pop出一个元素,然后跟min比较,假如等于min,那说明下一个元素是旧的min,我们更新min为 stack.pop(), 也把这个旧的min pop出来
    3. top 直接返回 stack.peek();
    4. getMin直接返回min
    class MinStack {
        private Stack<Integer> stack = new Stack<>();
        int min = Integer.MAX_VALUE;
        
        public void push(int x) {
            if (x <= min) {
                stack.push(min);
                min = x;
            }
            stack.push(x);
        }
    
        public void pop() {
            int peek = stack.pop();
            if (peek == min) min = stack.pop();
        }
    
        public int top() {
            return stack.peek();
        }
    
        public int getMin() {
            return min;
        }
    }

    Update:

    许多题目现在必须追求最优解了 -____-!!

    public class MinStack {
        private Stack<Integer> stack = new Stack<>();
        private int min = Integer.MAX_VALUE
    
        /** initialize your data structure here. */
        public MinStack() {
            stack = new Stack<>();
        }
        
        public void push(int x) {
            if (x <= min) {
                stack.push(min);
                min = x;
            }
            stack.push(x);
        }
        
        public void pop() {
            int top = stack.pop();
            if (top == min) min = stack.pop();
        }
        
        public int top() {
            return stack.peek();
        }
        
        public int getMin() {
            return min;
        }
    }
    
    /**
     * Your MinStack object will be instantiated and called as such:
     * MinStack obj = new MinStack();
     * obj.push(x);
     * obj.pop();
     * int param_3 = obj.top();
     * int param_4 = obj.getMin();
     */

    Reference:

    http://www.geeksforgeeks.org/design-and-implement-special-stack-data-structure/

    https://leetcode.com/discuss/21071/java-accepted-solution-using-one-stack

    https://leetcode.com/discuss/15679/share-my-java-solution-with-only-one-stack

    https://leetcode.com/discuss/19389/java-solution-accepted

    https://leetcode.com/discuss/23927/smart-accepted-java-solution-linked-list

    https://leetcode.com/discuss/16029/shortest-and-fastest-1-stack-and-2-stack-solutions

  • 相关阅读:
    利用数组将九种颜色不重复的显示在九个盒子中
    gulp结合webpack开启多页面模式,配置如下
    parent获取子元素以及自身元素
    利用键值对来找对应值的信息
    Math.random 随机数方法
    常用linux,DOS命令——持续更新
    函数嵌套函数传递this值
    空对象模式
    状态模式(状态机)
    观察者模式
  • 原文地址:https://www.cnblogs.com/yrbbest/p/4489706.html
Copyright © 2011-2022 走看看