3.(155)最小栈
Posted ningdeblog
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了3.(155)最小栈相关的知识,希望对你有一定的参考价值。
2020年3月21日
Design a stack that supports push, pop, top, and retrieving the minimum element in constant time.
- push(x) -- Push element x onto stack.
- pop() -- Removes the element on top of the stack.
- top() -- Get the top element.
- getMin() -- Retrieve the minimum element in the stack.
Example:
MinStack minStack = new MinStack();
minStack.push(-2);
minStack.push(0);
minStack.push(-3);
minStack.getMin(); --> Returns -3.
minStack.pop();
minStack.top(); --> Returns 0.
minStack.getMin(); --> Returns -2.
设计一个支持 push,pop,top 操作,并能在常数时间内检索到最小元素的栈。
- push(x) -- 将元素 x 推入栈中。
- pop() -- 删除栈顶的元素。
- top() -- 获取栈顶元素。
- getMin() -- 检索栈中的最小元素。
示例:
MinStack minStack = new MinStack();
minStack.push(-2);
minStack.push(0);
minStack.push(-3);
minStack.getMin(); --> 返回 -3.
minStack.pop();
minStack.top(); --> 返回 0.
minStack.getMin(); --> 返回 -2.
方法1
最直接的方法是用两个栈,一个保存正常的入栈出栈的值,另一个栈去存最小值,也就是用当前栈顶保存当前所有元素的最小值,流程如下:
- 将第一个元素入栈
- 新加入的元素如果大于栈顶元素,那么新加入的元素就不处理
- 新加入元素如果小于等于栈顶元素,那么新元素入栈
- 出栈元素不等于栈顶元素,不操作
- 出栈元素等于栈顶元素,将栈顶元素出栈
class MinStack{
private Stack<Integer> stack;
private Stack<Integer> minStack;
public MinStack(){
stack=new Stack<>();
minStack=new Stack<>();
}
public void push(int x){
stack.push(x);
if(!minStack.isEmpty()){
int top=minStack.peek();
//小于等于的时候才入栈
if(x<=top){
minStack.push(x);
}
}else{
minStack.push(x);
}
}
public void pop(){
int pop=stack.pop();
int top=minStack.peek();
//等于的时候再出栈
if(pop==top){
minStack.pop();
}
}
public int top(){
return stack.peek();
}
public int getMin(){
return minStack.peek();
}
public int getMin(){
return minStack.peek();
}
}
方法2
方法1中使用了两个栈实现,那么现在尝试用一个栈实现,只用一个变量去保存最小值,如果新压入的值更小,那么在压入新元素前将原来的min压入栈中,并更新最小值
class minStack{
int min = Integer.MIN_VALUE;
Stack<Integer> stack = new Stack<Integer>();
public void push(int x){
if(x<=min){
stack.push(min);
min=x;
}
stack.push(x);
}
public void pop(){
if(stack.pop()==min){
min = stack.pop();
}
}
public int top(){
return stack.peek();
}
public int getMin(){
return min;
}
}
方法3
从方法2中可以看出,关键要解决的问题是当有新的更小值的时候,之前的最小值怎么办?
方法3用另一种思路,通过min存储当前最小值,栈中存储入栈的值与最小值的差值
public class MinStack{
long min;
Stack<long> stack;
public MinStack(){
stack=new Stack<>();
}
public void push(int x){
if(stack.isEmpty()){
min=x;
stack.push(x-min);
}else{
stack.push(x-min);
if(x<min){
min=x;
}
}
}
public void pop(){
if(stack.isEmpty()) return;
long pop = stack.pop();
if(pop<0){
min=min-pop;
}
}
public int top(){
long top=stack.peek();
if(top<0){
return (int)(min);
}else{
return (int)(top+min);
}
}
public int getMin(){
return (int) min;
}
}
上述解法的一个缺点是保存的是差值,所以可能造成溢出,所以用了范围更大的long类型,这个解法在最小值更新时不需要把之前的最小值存起来,会节省一些空间
方法4
不用java提供的stack,在Node结点中增加min字段
class MinStack{
class Node{
int value;
int min;
Node next;
Node(int x,int min){
this.value=x;
this.min=min;
next=null;
}
}
Node head;
public void push(int x){
if(null==head){
head=new Node(x,x);
}else{
Node n = new Node(x,Math.min(x,head.min))
n.next=head;
head=n;
}
}
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;
}
}
以上是关于3.(155)最小栈的主要内容,如果未能解决你的问题,请参考以下文章