剑指offer-20、包含min函数的栈

题⽬描述

定义栈的数据结构,请在该类型中实现⼀个能够得到栈中所含最⼩元素的min 函数(时间复杂度为O(1) )。

此栈包含的⽅法有:

  • push(value) :将value 压⼊栈中
  • pop() :弹出栈顶元素
  • top() :获取栈顶元素
  • min() :获取栈中最⼩元素

思路及解答

双栈法(推荐,实现简单)

使用两个栈:

  1. 主栈:存储所有元素
  2. 辅助栈:存储当前主栈中的最小值

push ⼀个元素的时候,都需要push 进datas stack ,但是push 进⼊mins stack 需要满⾜条件:当前的mins stack 是空的,直接放⼊。或者当前的mins stack 的栈顶元素⼤于或者等于push 进来的值。

pop ⼀个元素的时候,如果栈为空则什么都不操作,如果栈不为空,则判断datas 的第⼀个元素是否和mins 的第⼀个元素相等。如果相等的话那么就需要将mins 和datas pop 出去第⼀个元素,否则只需要将datas 的第⼀个元素 pop 出去即可。

java 复制代码
public class Solution {
	private Stack<Integer> datas = new Stack<>();
	private Stack<Integer> mins = new Stack<>();

	/​**​
     * 将元素压入栈中
     * @param value 要压入的值
     */
	public void push(int node) {
		datas.push(node);
		// 如果辅助栈为空,或新值<=当前最小值,压入辅助栈
		if (mins.isEmpty()) {
			mins.push(node);
		} else {
			int min = mins.peek();
			if (node <= min) {
				mins.push(node);
			}
		}
	}
	
	public void pop() {
		if (datas.isEmpty()) {
			return;
		} else {
			int value = datas.peek();
			if (value == mins.peek()) {
				mins.pop();
			}
			datas.pop();
		}
	}
	
	public int top() {
		if(datas.isEmpty()){
			return -1;
		}
		return datas.peek();
	}
	
	public int min() {
		if(mins.isEmpty()){
			return -1;
		}
		return mins.peek();
	}
}
  • 时间复杂度: O(1)
  • 空间复杂度: O(n) ,借助了辅助栈。

差值法

使用一个栈和一个变量minValue

  1. 栈存储差值:存储元素与当前最小值的差值
  2. 更新最小值:当遇到更小值时,先存储当前差值(负值),再更新最小值
  3. 恢复前值pop时如果发现差值为负,说明此处发生过最小值更新,需要恢复前一个最小值
java 复制代码
public class Solution {
    private Stack<Long> stack = new Stack<>();; // 存储差值的栈
    private long minValue; // 当前最小值

    public void push(int value) {
        if (stack.isEmpty()) {
            minValue = value;
            stack.push(0L); // 差值为0
        } else {
            long diff = (long)value - minValue;
            stack.push(diff);
            // 如果差值为负,说明value是新的最小值
            if (diff < 0) {
                minValue = value;
            }
        }
    }

    public void pop() {
        if (stack.isEmpty()) {
            return;
        }
        long diff = stack.pop();
        // 如果差值为负,说明此处更新过最小值,需要恢复前一个最小值
        if (diff < 0) {
            minValue = minValue - diff;
        }
    }

    public int top() {
        if (stack.isEmpty()) {
           return;
        }
        long diff = stack.peek();
        // 如果差值为负,说明当前栈顶就是最小值
        if (diff < 0) {
            return (int)minValue;
        } else {
            return (int)(minValue + diff);
        }
    }

    public int min() {
        if (stack.isEmpty()) {
           return;
        }
        return (int)minValue;
    }
}
  • 时间复杂度:所有操作仍为O(1)
  • 空间复杂度:O(1)额外空间(仅一个变量),但栈存储的是差值而非原始值

需要考虑整数溢出问题(使用long存储差值)

相关推荐
Java中文社群1 小时前
抱歉!Java面试标准答案最不重要
java·后端·面试
Java小Y2 小时前
redis(2)-java客户端使用(IDEA基于springboot)
java·redis·intellij-idea
herderl2 小时前
【无标题】命名管道(Named Pipe)是一种在操作系统中用于**进程间通信(IPC)** 的机制
java·linux·服务器·嵌入式硬件·php
笑衬人心。2 小时前
缓存的三大问题分析与解决
java·spring·缓存
用户84913717547163 小时前
JDK 17 实战系列(第7期):迁移指南与最佳实践
java·jvm
duration~3 小时前
SpringAI实现Reread(Advisor)
java·人工智能·spring boot·spring
我们从未走散3 小时前
面试题-----微服务业务
java·开发语言·微服务·架构
YuforiaCode3 小时前
24SpringCloud黑马商城微服务整合Seata重启服务报错的解决办法
java·spring·微服务
考虑考虑3 小时前
JDK21中的Sequenced Collections(序列集合)
java·后端·java ee