地址 https://leetcode-cn.com/problems/bao-han-minhan-shu-de-zhan-lcof/
定义栈的数据结构,请在该类型中实现一个能够得到栈的最小元素的 min 函数在该栈中,调用 min、push 及 pop 的时间复杂度都是 O(1)。 示例: MinStack minStack = new MinStack(); minStack.push(-2); minStack.push(0); minStack.push(-3); minStack.min(); --> 返回 -3. minStack.pop(); minStack.top(); --> 返回 0. minStack.min(); --> 返回 -2. 提示: 各函数的调用总次数不超过 20000 次 注意:本题与主站 155 题相同:https://leetcode-cn.com/problems/min-stack/
解答
栈的操作基本没有变化 ,关键在于如何获取当前序列中最小的数。
最开始考虑使用最小堆,但是最小堆的弹出的时间复杂度达不到题目要求
我们从减少最小堆的不必要的存储和弹出的操作入手。如果当前push 的数据比最小堆的顶端最小数目大的话那么就不必push进入堆,
因为该数字push进容器内,它在容器内的存活周期中他的下面始终有一个存活周期比它长比他小的数字,所以它的push和pop是没有必要的
于是就可以大量减少最小堆的操作。
代码如下
class MinStack { public: /** initialize your data structure here. */ stack<int>data; priority_queue<int, vector<int>, greater<int>> minHeap; MinStack() { } void push(int x) { data.push(x); if (minHeap.empty() || x <= minHeap.top() ) minHeap.push(x); } void pop() { if (data.empty()) return; int x = data.top(); data.pop(); if (x <= minHeap.top()) minHeap.pop(); } int top() { return data.top(); } int min() { if (!minHeap.empty()) return minHeap.top(); return -999999; } };
进一步的优化,观察以上的堆的操作
堆的操作已经演变成一个只记录当前最小数字的单调栈了
那么直接使用两个栈就可以完成以上操作
========================================================================================
class MinStack { public: /** initialize your data structure here. */ stack<int>data; stack<int>currMin; MinStack() { } void push(int x) { data.push(x); if (currMin.empty() || x <= currMin.top() ) currMin.push(x); } void pop() { if (data.empty()) return; int x = data.top(); data.pop(); if (x <= currMin.top()) currMin.pop(); } int top() { return data.top(); } int min() { if (!currMin.empty()) return currMin.top(); return -999999; } };