zoukankan      html  css  js  c++  java
  • 最小栈问题

    题目:如何实现一个栈,既存在基本的push pop操作,又可以有getMin操作,注:元素均是int型

    原始方法:维持一个变量,使之保存入栈的最小值,当第一个最小值出去后,遍历剩下的栈元素并更新最小值变量,这种算法pop的时间复杂度是O(n),其他操作的时间复杂度都是O(1),空间复杂度是O(1);

    改进1:如果可以申请一个连续内存来存放不同阶段的最小值,那么就不需要每次遍历了,典型的空间换时间。最方便的是申请一个栈min,每次push的时候,如果是比当下最小值还要小,则也push进min栈,否则min栈重复push当前最小值,也就是说保持两个栈元素数量一致,这样每次pop的时候,min栈顶元素就是当前的最小值。时间复杂度为O(1),空间复杂度为O(n)

    import java.util.ArrayList;
    import java.util.List;
     
    public class MinStack {
     
        private List<Integer> data = new ArrayList<Integer>();
        private List<Integer> mins = new ArrayList<Integer>();
     
        public void push(int num) {
            data.add(num);
            if(mins.size() == 0) {
                // 初始化mins
                mins.add(num);
            } else {
                // 辅助栈mins每次push当时最小值
                int min = getMin();
                if (num >= min) {
                    mins.add(min);
                } else {
                    mins.add(num);
                }
            }
        }
     
        public int pop() {
            // 栈空,异常,返回-1
            if(data.size() == 0) {
                return -1;
            }
            // pop时两栈同步pop
            mins.remove(mins.size() - 1);
            return data.remove(data.size() - 1);
        }
     
        public int getMin() {
            // 栈空,异常,返回-1
            if(mins.size() == 0) {
                return -1;
            }
            // 返回mins栈顶元素
            return mins.get(mins.size() - 1);
        }
     
    }

    该进2:我们发现上面的算法存在大量的重复元素,因此还有可优化空间。如果新push的值不小于最小值,在min栈里我们可以不重复push最小值,在pop的时候,我们先判断栈顶元素与min栈顶元素是否相同,如果相同min栈一同pop,否则min栈不动。当然,如果新push的元素大小与最小值相同,也要入min栈,这样才能保证数据正确性。

    改进3:我们发现上面的算法还是会存在重复元素,也就是多个相同最小值入栈的时候。那么如何改进呢?用索引!在min栈中存储第一次出现最小值的索引,这样当重复出现最小值的时候无需重复存入,pop的时候只需要判断最小值索引还在不在即可,当索引pop的时候,min栈也随之pop,否则min栈不用动。

    import java.util.ArrayList;
    import java.util.List;
     
    public class MinStack {
     
        private List<Integer> data = new ArrayList<Integer>();
        private List<Integer> mins = new ArrayList<Integer>();
     
        public void push(int num) throws Exception {
            data.add(num);
            if(mins.size() == 0) {
                // 初始化mins
                mins.add(0);
            } else {
                // 辅助栈mins push最小值的索引
                int min = getMin();
                if (num < min) {
                    mins.add(data.size() - 1);
                }
            }
        }
     
        public int pop() throws Exception {
            // 栈空,抛出异常
            if(data.size() == 0) {
                throw new Exception("栈为空");
            }
            // pop时先获取索引
            int popIndex = data.size() - 1;
            // 获取mins栈顶元素,它是最小值索引
            int minIndex = mins.get(mins.size() - 1);
            // 如果pop出去的索引就是最小值索引,mins才出栈
            if(popIndex == minIndex) {
                mins.remove(mins.size() - 1);
            }
            return data.remove(data.size() - 1);
        }
     
        public int getMin() throws Exception {
            // 栈空,抛出异常
            if(data.size() == 0) {
                throw new Exception("栈为空");
            }
            // 获取mins栈顶元素,它是最小值索引
            int minIndex = mins.get(mins.size() - 1);
            return data.get(minIndex);
        }
     
    }
  • 相关阅读:
    centos7 安装docker 对应的 rabbitmq3.6.15
    golang中defer的使用规则
    Yii2-redis 不用 composer 的安装
    安装并使用PHPunit
    PHP Taint – 一个用来检测XSS/SQL/Shell注入漏洞的扩展
    SQL Antipatterns——SQL 反模式(二)
    tp5 No input file specified.
    vue 封装自定义组件
    判断微信访问
    phalcon windows下安装phalcon-devtools 官网的坑
  • 原文地址:https://www.cnblogs.com/ZoHy/p/11325003.html
Copyright © 2011-2022 走看看