设计一个支持 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 操作总是在 非空栈 上调用。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/min-stack
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
方法一:两个栈
一个栈保存正常的入栈出栈值,一个栈保存当前所有元素的最小值
最小栈的具体操作流程如下:
1.将第一个元素入栈
2.添加的元素小于等于栈顶元素,则入栈;否则,不作处理
3.出栈的元素等于栈顶元素,则出栈,否则不作处理
class MinStack {
/**
* initialize your data structure here.
*/
private Stack stack;
private Stack minStack;
public MinStack() {
stack = new Stack<>();
minStack = new Stack<>();
}
public void push(int x) {
stack.push(x);
//minStack为空添加元素,否则判断栈顶元素与新添加元素值大小
if (!minStack.isEmpty()) {
if (x <= minStack.peek()) {
minStack.push(x);
}
} else {
minStack.push(x);
}
}
public void pop() {
int x = stack.pop();
int peek = minStack.peek();
if (x == peek) {
minStack.pop();
}
}
//使用peek,不出栈
public int top() {
return stack.peek();
}
public int getMin() {
return minStack.peek();
}
}
方法二:只使用一个栈,定义变量min保存最小值
存在问题:
1.假设栈中最小元素为min,新添加元素为x,小于min,将min更新为x,但是之前的最小值min则丢失了
解决方法:如果新添加元素x小于min,先将min压栈,将x赋值min,再将最小值x压栈
2.如果出栈元素为最小值,该如何?
解决方法:先将最小值出栈,再出栈一次,将最小值赋值。
class MinStack {
/** initialize your data structure here. */
int min = Integer.MAX_VALUE;;
Stack stack;
public MinStack() {
stack = new Stack<>();
}
public void push(int x) {
//判断新添加元素与min值大小
if (x <= min) {
stack.push(min);
min = x;
}
stack.push(x);
}
public void pop() {
//使用stack.pop()先出栈,判断出栈元素为最小值,需要再出栈一次
if (stack.pop() == min) {
min = stack.pop();
}
}
public int top() {
return stack.peek();
}
public int getMin() {
return min;
}
}
方法三:基于方法二修改
1.使用一个栈,增加变量min保存最小值
2.压栈元素为 入栈元素-min
3.差值小于0,将新压栈元素赋值min,之前min则等于min-栈顶元素
4.出栈时,栈顶元素小于0时,更新min为min-栈顶元素,返回min为栈顶元素;否则,出栈元素为min+栈顶元素
注意:使用long保存栈中元素,防止内存溢出
class MinStack {
/** initialize your data structure here. */
long min;
Stack stack;
public MinStack() {
stack = new Stack<>();
}
public void push(int x) {
//需判断stack是否为空
if (stack.isEmpty()) {
min = x;
stack.push(x - min);
} else {
stack.push(x - min);
if (x <= min) {
min = x;
}
}
}
public void pop() {
long pop = stack.pop();
//更新min值
if (pop <= 0) {
min = min - pop;
}
}
public int top() {
long peek = stack.peek();
if (peek <= 0) {
return (int) min;
} else {
return (int) (peek + min);
}
}
public int getMin() {
return (int) min;
}
}
方法四:不使用Java自带的Stack
使用链表实现栈的功能,定义Node节点时增加min字段,每次保存元素时更新min值
每次添加元素到头部
class MinStack {
/**
* initialize your data structure here.
*/
class ListNode{
int value;
int min;
ListNode next;
ListNode(int x, int min) {
this.value = x;
this.min = min;
next = null;
}
}
ListNode head;
public MinStack() {
}
public void push(int x) {
if (head == null) {
head = new ListNode(x, x);
} else {
ListNode node = new ListNode(x, Math.min(head.min, x));
node.next = head;
head = node;
}
}
public void pop() {
if (head != null) {
head = head.next;
}
}
public int top() {
if (head != null) {
return head.value;
}
return -1;
}
public int getMin() {
if (head != null) {
return head.min;
}
return -1;
}
}