每日一道 LeetCode (35):最小栈
每天 3 分钟,走上算法的逆袭之路。
前文合集
代码仓库
GitHub: https://github.com/meteor1993/LeetCode
Gitee: https://gitee.com/inwsy/LeetCode
题目:最小栈
题目来源:https://leetcode-cn.com/problems/min-stack/
设计一个支持 push ,pop ,top 操作,并能在常数时间内检索到最小元素的栈。
push(x) —— 将元素 x 推入栈中。
pop() —— 删除栈顶的元素。
top() —— 获取栈顶元素。
getMin() —— 检索栈中的最小元素。
示例:
输入:
["MinStack","push","push","push","getMin","pop","top","getMin"]
[[],[-2],[0],[-3],[],[],[],[]]
输出:
[null,null,null,null,-3,null,0,-2]
解释:
MinStack minStack = new MinStack();
minStack.push(-2);
minStack.push(0);
minStack.push(-3);
minStack.getMin(); --> 返回 -3.
minStack.pop();
minStack.top(); --> 返回 0.
minStack.getMin(); --> 返回 -2.
```
提示:
- pop、top 和 getMin 操作总是在 非空栈 上调用。
## 解题思路
看到这道题的第一个反应,这不就是一个数据结构栈么, Java 直接提供了啊,这还用做么?
当我把题仔细的又读了一遍以后发现,这里面有一个 `getMin()` 检索栈中的最小元素是 JDK 所没有提供的,那么这道题实际上就是在问,如何在栈的数据结构中检索栈中最小的元素。
经过一番仔细的思索,嗯,确认是我不会的那道题。
这就很尴尬了,打开答案看答案吧。
答案上的结果是加一个辅助栈来进行记录,记录添加到栈里最小的元素。。。
好吧,我服了,这方案确实可以。
往下翻了翻,结果还有人玩的更花,还把这个方案拆分成两种方案:同步法和不同步法。
直接一个大写的 NB 。
## 方案一:同步法
所谓的同步法就是在向数据栈中添加元素的时候,一起向辅助栈中也添加元素,数据栈出栈的时候辅助栈也一起出栈,辅助栈最后添加进来的数字保持最小,只有当将要进栈的数字比栈顶的数字小才能进栈,否则就将和栈顶的数字一样的数字重新进一次栈。
```java
public class MinStack {
private Stack<Integer> data;
private Stack<Integer> helper;
/** initialize your data structure here. */
public MinStack() {
data = new Stack<> ();
helper = new Stack<> ();
}
public void push(int x) {
data.push(x);
// 只有小于栈顶的数字才能进栈,否则重新将栈顶的数字进栈
if (helper.isEmpty() || helper.peek() >= x) {
helper.push(x);
} else {
helper.push(helper.peek());
}
}
public void pop() {
if (!data.isEmpty()) {
data.pop();
helper.pop();
}
}
public int top() {
if (!data.isEmpty()) {
return data.peek();
}
throw new RuntimeException("栈中元素为空,非法操作");
}
public int getMin() {
if(!helper.isEmpty()){
return helper.peek();
}
throw new RuntimeException("栈中元素为空,此操作非法");
}
}
方案二:不同步法
上面的同步法是只数据栈和辅助栈进栈出栈都是同步操作的,那么在外面的辅助栈中,能不能只存最小的值,因为它本身设计的使命就是用来查询最小值的。
public class MinStack1 {
private Stack<Integer> data;
private Stack<Integer> helper;
/** initialize your data structure here. */
public MinStack1() {
data = new Stack<> ();
helper = new Stack<> ();
}
public void push(int x) {
data.push(x);
// 辅助栈只会进栈小值
if (helper.isEmpty() || helper.peek() >= x) {
helper.push(x);
}
}
public void pop() {
if (!data.isEmpty()) {
int top = data.pop();
// 只有当出栈的值也是小值的时候辅助栈也出栈
if(top == helper.peek()){
helper.pop();
}
}
}
public int top() {
if (!data.isEmpty()) {
return data.peek();
}
throw new RuntimeException("栈中元素为空,非法操作");
}
public int getMin() {
if(!helper.isEmpty()){
return helper.peek();
}
throw new RuntimeException("栈中元素为空,此操作非法");
}
}
耗时和前面的方法是一样的,只是我们所使用的辅助栈的空间变小了,但是在出栈的时候需要经过判断才能出栈。
扫描二维码关注「极客挖掘机」公众号!
作者:极客挖掘机
定期发表作者的思考:技术、产品、运营、自我提升等。
本文版权归作者极客挖掘机和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
如果您觉得作者的文章对您有帮助,就来作者个人小站逛逛吧:极客挖掘机
作者:极客挖掘机
定期发表作者的思考:技术、产品、运营、自我提升等。
本文版权归作者极客挖掘机和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
如果您觉得作者的文章对您有帮助,就来作者个人小站逛逛吧:极客挖掘机
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?
2019-09-03 Spring Cloud Alibaba | Gateway基于Nacos动态网关路由