当前位置: 首页 > news >正文

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

相关文章:

  • DataTables ajax重新加载数据
  • SVN更新的问题
  • Windows服务器配置与管理DHCP服务器搭建与管理
  • 线程:Message和Runnable
  • css3实现手机效果的“切换标签”
  • Exchange 2010与Exchange Online混合部署PART 6:邮箱测试
  • nginx配置及HTTPS配置示例
  • LeetCode - Isomorphic Strings
  • php的应用注意点
  • Android Eclipse下开发环境搭建
  • Java加密技术(九)——初探SSL
  • NFS服务安装配置
  • 【leetcode】Integer to Roman Roman to Integer(easy)
  • Java wshh
  • 一个程序员眼中的北京和上海
  • JavaScript 如何正确处理 Unicode 编码问题!
  • Angular6错误 Service: No provider for Renderer2
  • extjs4学习之配置
  • java2019面试题北京
  • JavaScript实现分页效果
  • js数组之filter
  • KMP算法及优化
  • miaov-React 最佳入门
  • Sublime Text 2/3 绑定Eclipse快捷键
  • Vue组件定义
  • 代理模式
  • 基于Android乐音识别(2)
  • 聊一聊前端的监控
  • 前端学习笔记之观察者模式
  • 如何在GitHub上创建个人博客
  • 设计模式 开闭原则
  • 通过git安装npm私有模块
  • 一文看透浏览器架构
  • 在GitHub多个账号上使用不同的SSH的配置方法
  • #Js篇:单线程模式同步任务异步任务任务队列事件循环setTimeout() setInterval()
  • #Lua:Lua调用C++生成的DLL库
  • #我与Java虚拟机的故事#连载03:面试过的百度,滴滴,快手都问了这些问题
  • $分析了六十多年间100万字的政府工作报告,我看到了这样的变迁
  • (PyTorch)TCN和RNN/LSTM/GRU结合实现时间序列预测
  • (附源码)计算机毕业设计SSM智慧停车系统
  • (切换多语言)vantUI+vue-i18n进行国际化配置及新增没有的语言包
  • (一) storm的集群安装与配置
  • .NET I/O 学习笔记:对文件和目录进行解压缩操作
  • .NET(C#) Internals: as a developer, .net framework in my eyes
  • .netcore 6.0/7.0项目迁移至.netcore 8.0 注意事项
  • .NetCore部署微服务(二)
  • .NET简谈互操作(五:基础知识之Dynamic平台调用)
  • .NET框架
  • .NET运行机制
  • [20150321]索引空块的问题.txt
  • [2023年]-hadoop面试真题(一)
  • [BZOJ4554][TJOI2016HEOI2016]游戏(匈牙利)
  • [C/C++]_[初级]_[关于编译时出现有符号-无符号不匹配的警告-sizeof使用注意事项]
  • [C++][数据结构][算法]单链式结构的深拷贝
  • [CISCN 2023 初赛]go_session