害,昨天犯懒,一晚上没学习,就没做(爬
今天补上
题目描述
设计一个最小栈,可以完成栈最基本的push、pop、top功能,除此之外要实现一个getMin方法,在常数时间内得到当前栈中的最小值
解题思路
(1)一个不符合题目要求的做法:使用List结构来模拟栈的操作,push即加入list,pop和top则是操作list的最后一个元素,getMin则需要对list进行一个遍历操作找到最小值。由于需要遍历,getMin的时间复杂度为O(N),不符合题目要求。
(2) 想办法存下最小值。因为题目要求在常数时间内返回最小值,那么就意味着我们必须采用某种方法提前存下最小值,而不是等到要获得最小值时才去所有的数里面找。对于正常存入最小栈中的数据,我们可以就直接采用一个栈来保存,而对于保存最小值,有以下几种方法:
图片解说来自题解:https://leetcode-cn.com/problems/min-stack/solution/xiang-xi-tong-su-de-si-lu-fen-xi-duo-jie-fa-by-38/
法一: 使用一个额外的栈保存最小值。
在最开始的时候我考虑过用一个额外的变量来保存最小值,而变量的问题在于:当前最小值被pop出去之后,第二小的元素(即pop之后的最小值)应该怎么获取?也就是说,在这道题目中,保存最小值并非只保存一个当前数据就可以,而是要保存一个 “最小值序列”。
因此就会想到,是不是可以用一个额外的数据结构来保存这个最小值序列呢?
法一就是使用了一个额外的栈,具体做法是:当第一个元素入栈时,将其加入最小栈;后续元素入(基本)栈时,将其与最小栈的栈顶比较,如果比栈顶元素大,就不管,反之就将这个元素加入最小栈
代码如下:
class MinStack {
/** initialize your data structure here. */
Stack<Integer> stack;
Stack<Integer> minStack;
public MinStack() {
this.stack = new Stack<>();
this.minStack = new Stack<>();
}
public void push(int x) {
stack.push(x);
if (minStack.size() == 0 || x <= minStack.peek()) {
minStack.push(x);
}
}
public void pop() {
int tmp = stack.peek();
stack.pop();
if (minStack.peek() == tmp) {
minStack.pop();
}
}
public int top() {
return stack.peek();
}
public int getMin() {
return minStack.peek();
}
}
法二: 只使用一个栈,同时保存数据序列和最小值。
主要问题就是,当最小值有更新的时候,如何把前一个最小值保存下来。只使用一个栈时可以进行如下操作:
(1)当最小值更新时,先将前一个最小值压栈,然后更新最小值且将当前最小值压栈
(2)当出栈的数值和当前最小值相等时,再进行一次出栈操作,也就是恢复前一个最小值
(按照这个思路写的代码也比较简单,就不再重复了)
(3) (2)中的方法都是基于直接使用Java的栈来保存数据序列,当然我们也可以不用自带的栈,可以考虑用一个链表,在每一个Node节点中都增加一个min字段,每次push的时候就确定该node的min值,直接从底层数据结构就解决了最小值的问题。
这里需要注意,由于我们每次都是操作栈顶元素,因此每次push的时候都可以将节点加入首部
以下代码来自题解,也比较简单:
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{
//当前值和之前头结点的最小值较小的做为当前的 min
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(null!=head)
return head.min;
return -1;
}
}