[LeetCode] Max Stack 最大栈
Design a max stack that supports push, pop, top, peekMax and popMax.
- push(x) -- Push element x onto stack.
- pop() -- Remove the element on top of the stack and return it.
- top() -- Get the element on the top.
- peekMax() -- Retrieve the maximum element in the stack.
- popMax() -- Retrieve the maximum element in the stack, and remove it. If you find more than one maximum elements, only remove the top-most one.
Example 1:
MaxStack stack = new MaxStack();
stack.push(5);
stack.push(1);
stack.push(5);
stack.top(); -> 5
stack.popMax(); -> 5
stack.top(); -> 1
stack.peekMax(); -> 5
stack.pop(); -> 1
stack.top(); -> 5
Note:
- -1e7 <= x <= 1e7
- Number of operations won't exceed 10000.
- The last four operations won't be called when stack is empty.
这道题让我们实现一个最大栈,包含一般栈的功能,但是还新加了两个功能peekMax()和popMax(),随时随地可以查看和返回最大值。之前有一道很类似的题Min Stack,所以我们可以借鉴那道题的解法,使用两个栈来模拟,s1为普通的栈,用来保存所有的数字,而s2为最大栈,用来保存出现的最大的数字。
在push()函数中,我们先来看s2,如果s2为空,或者s2的栈顶元素小于等于x,将x压入s2中。因为s2保存的是目前为止最大的数字,所以一旦新数字大于等于栈顶元素,说明遇到更大的数字了,压入栈。然后将数组压入s1,s1保存所有的数字,所以都得压入栈。
在pop()函数中,当s2的栈顶元素和s1的栈顶元素相同时,我们要移除s2的栈顶元素,因为一个数字不在s1中了,就不能在s2中。然后取出s1的栈顶元素,并移除s1,返回即可。
在top()函数中,直接返回s1的top()函数即可。
在peekMax()函数中,直接返回s2的top()函数即可。
在popMax()函数中,先将s2的栈顶元素保存到一个变量mx中,然后我们要在s1中删除这个元素,由于栈无法直接定位元素,所以我们用一个临时栈t,将s1的出栈元素保存到临时栈t中,当s1的栈顶元素和s2的栈顶元素相同时退出while循环,此时我们在s1中找到了s2的栈顶元素,分别将s1和s2的栈顶元素移除,然后要做的是将临时栈t中的元素加回s1中,注意此时容易犯的一个错误是,没有同时更新s2,所以我们直接调用push()函数即可,参见代码如下:
解法一:
class MaxStack {
public:
/** initialize your data structure here. */
MaxStack() {}
void push(int x) {
if (s2.empty() || s2.top() <= x) s2.push(x);
s1.push(x);
}
int pop() {
if (!s2.empty() && s2.top() == s1.top()) s2.pop();
int t = s1.top(); s1.pop();
return t;
}
int top() {
return s1.top();
}
int peekMax() {
return s2.top();
}
int popMax() {
int mx = s2.top();
stack<int> t;
while (s1.top() != s2.top()) {
t.push(s1.top()); s1.pop();
}
s1.pop(); s2.pop();
while (!t.empty()) {
push(t.top()); t.pop();
}
return mx;
}
private:
stack<int> s1, s2;
};
下面这种解法没有利用一般的stack,而是建立一种较为复杂的数据结构,首先用一个list链表来保存所有的数字,然后建立一个数字和包含所有相同的数字的位置iterator的向量容器的映射map。
在push()函数中,把新数字加到list表头,然后把数字x的位置iterator加到数字映射的向量容器的末尾。
在pop()函数中,先得到表头数字,然后把该数字对应的iterator向量容器的末尾元素删掉,如果此时向量容器为空了,将这个映射直接删除,移除表头数字,返回该数字即可。
在top()函数中,直接返回表头数字即可。
在peekMax()函数中,因为map是按key值自动排序的,直接尾映射的key值即可。
在popMax()函数中,首先保存尾映射的key值,也就是最大值到变量x中,然后在其对应的向量容器的末尾取出其在list中的iterator。然后删除该向量容器的尾元素,如果此时向量容器为空了,将这个映射直接删除。根据之前取出的iterator,在list中删除对应的数字,返回x即可,参见代码如下:
解法二:
class MaxStack {
public:
/** initialize your data structure here. */
MaxStack() {}
void push(int x) {
v.insert(v.begin(), x);
m[x].push_back(v.begin());
}
int pop() {
int x = *v.begin();
m[x].pop_back();
if (m[x].empty()) m.erase(x);
v.erase(v.begin());
return x;
}
int top() {
return *v.begin();
}
int peekMax() {
return m.rbegin()->first;
}
int popMax() {
int x = m.rbegin()->first;
auto it = m[x].back();
m[x].pop_back();
if (m[x].empty()) m.erase(x);
v.erase(it);
return x;
}
private:
list<int> v;
map<int, vector<list<int>::iterator>> m;
};
类似题目:
参考资料:
https://discuss.leetcode.com/topic/110014/c-using-two-stack
https://discuss.leetcode.com/topic/110066/c-o-logn-for-write-ops-o-1-for-reads
LeetCode All in One 题目讲解汇总(持续更新中...)
[LeetCode] Max Stack 最大栈的更多相关文章
- [leetcode]716. Max Stack 最大栈
Design a max stack that supports push, pop, top, peekMax and popMax. push(x) -- Push element x onto ...
- [LeetCode] Min Stack 最小栈
Design a stack that supports push, pop, top, and retrieving the minimum element in constant time. pu ...
- LeetCode Max Stack
原题链接在这里:https://leetcode.com/problems/max-stack/description/ 题目: Design a max stack that supports pu ...
- LeetCode Min Stack 最小值栈
题意:实现栈的四个基本功能.要求:在get最小元素值时,复杂度O(1). 思路:链表直接实现.最快竟然还要61ms,醉了. class MinStack { public: MinStack(){ h ...
- [LeetCode] 155. Min Stack 最小栈
Design a stack that supports push, pop, top, and retrieving the minimum element in constant time. pu ...
- LeetCode 155:最小栈 Min Stack
LeetCode 155:最小栈 Min Stack 设计一个支持 push,pop,top 操作,并能在常数时间内检索到最小元素的栈. push(x) -- 将元素 x 推入栈中. pop() -- ...
- 【LeetCode】716. Max Stack 解题报告(C++)
作者: 负雪明烛 id: fuxuemingzhu 个人博客:http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 双栈 日期 题目地址:https://leetcode ...
- leetcode Maximal Rectangle 单调栈
作者:jostree 转载请注明出处 http://www.cnblogs.com/jostree/p/4052721.html 题目链接:leetcode Maximal Rectangle 单调栈 ...
- [CareerCup] 3.2 Min Stack 最小栈
3.2 How would you design a stack which, in addition to push and pop, also has a function min which r ...
随机推荐
- logback常用配置详解及logback简介
logback 简介(一) Ceki Gülcü在Java日志领域世界知名.他创造了Log4J ,这个最早的Java日志框架即便在JRE内置日志功能的竞争下仍然非常流行.随后他又着手实现SLF4J 这 ...
- DFA算法的简单说明!
1.DFA算法简介 DFA全称为:Deterministic Finite Automaton,即确定有穷自动机.其特征为:有一个有限状态集合和一些从一个状态通向另一个状态的边,每条边上标记有一个符号 ...
- 自定义ArrayList
自定义实现ArrayList很简单,只需要明白下面几点 1.ArrayList 底层是由数组组成的 2.数组有容量限制,但是ArrayList并没有(实际上也有,Integer.MAX_VALUE). ...
- Spring学习笔记(1)
激发pojo的潜能,不会让pojo类继承实现或导入与Spring API相关的任何东西 那么spring怎么装配pojo呢-------->依赖注入(最大好处:松耦合) 耦合具有两面性: 一方面 ...
- JAVA多线程中start方法与run方法区别
start()方法告诉jvm该线程准备运行,jvm通过调用任务的run()方法执行任务. 一个任务类必须实现Runnable接口,而任务必须从线程运行. 实现Runnable接口后必须重写run()方 ...
- 20162302 实验一《Java开发环境的熟悉》实验报告
实 验 报 告 课程:程序设计与数据结构 姓名:杨京典 班级:1623 学号:20162302 实验名称:Java开发环境的熟悉 实验器材:装有Ubuntu的联想拯救者80RQ 实验目的与要求:1.使 ...
- OSI七层协议模型、TCP/IP四层模型学习笔记
1. OSI七层和TCP/IP四层的关系 1.1 OSI引入了服务.接口.协议.分层的概念,TCP/IP借鉴了OSI的这些概念建立TCP/IP模型. 1.2 OSI先有模型,后有协议,先有标准,后进行 ...
- js解决IE8不支持html5,css3的问题(respond.js 的使用注意)
IE8.0及以下不支持html5,css3的解析.目前为止IE8以下的版本使用率在10%左右,网站还是有必要兼容的. 1,在你的所有css最后判断引入两个js文件. html5.js 是用来让ie8 ...
- Linq 等式运算符:SequenceEqual
检查元素的数量,每个元素的值及两个集合中元素的顺序是否相等,3个方面都相等则为true,否则为false IList<string> strList1 = new List<stri ...
- Windows用户模式下注入方式总结
注入技术在病毒木马.游戏.打补丁等编程中应用很广泛,学习该技术不仅能帮助理解Windows工作原理,还能对病毒木马技术手段有更加深刻的理解,下面我们了解下各种注入方式吧. 一.DLL注入 在注入技术中 ...