题目要求
定义栈的数据结构,请在该类型中实现一个能够得到栈的最小元素的 min 函数在该栈中,调用 min、push 及 pop 的时间复杂度都是 O(1)。
题目分析
- 构造一个栈,栈具有先进后出的特点,且需要一个栈顶指针来指向栈的顶部
- 该栈需要能够返回其中最小的函数,且需要时间复杂度为O(1),因此就需要在push 和 pop操作的时候根据操作的值 记录得到一个min值,这样才能保证时间复杂度为O(1).
- 考虑到时间复杂度的要求及push和pop都是插入删除操作,因此可使用链表来实现栈的数据结构.
Java的LinkedList是一种常用的数据容器,与ArrayList相比,LinkedList的增删操作效率更高,而查改操作效率较低。
LinkedList 实现了List 接口,能对它进行列表操作。
LinkedList 实现了Deque 接口,能将LinkedList当作双端队列使用。
LinkedList 实现了Cloneable接口,能克隆。
LinkedList 实现了java.io.Serializable接口,这意味着LinkedList支持序列化,能通过序列化去传输。
具体的思路
具体就是使用两个LinkedList,A和 B, A用来实现栈,B用来存放该栈的一系列最小值,这个一系列最小值是怎么得来的呢?
具体来说就是,当执行push x操作的时候首先判断x是否小于等于B中的栈顶元素,若小于则push进B,否则就不push,这样当push操作执行完后,B中的栈顶元素返回的就是A的最小的元素min
在执行pop操作的时候,首先判断A中的栈顶元素是否等于B的栈顶,如果是,那么说明当前pop出去的是A的最小值,此时需要把B中的栈顶元素也pop出去。
class MinStack {
int min = Integer.MAX_VALUE;
int top = -1;
int tt = -1;
LinkedList<Integer> stack;
LinkedList<Integer> record;
/** initialize your data structure here. */
public MinStack() {
stack = new LinkedList();
record = new LinkedList();
}
public void push(int x) {
top++;
stack.add(top,x);
if(x<=min){
tt++;
record.add(tt,x);
min = x;
}
}
public void pop() {
if(stack.getLast() == record.getLast()){
record.remove(tt);
tt--;
}
stack.remove(top);
top--;
}
public int top() {
return stack.getLast();
}
public int min() {
return record.getLast();
}
}
/**
* Your MinStack object will be instantiated and called as such:
* MinStack obj = new MinStack();
* obj.push(x);
* obj.pop();
* int param_3 = obj.top();
* int param_4 = obj.min();
*/
其中LinkedList 方法的getLast() 方法定义为:
public E getLast(),返回最后一个元素,其返回的是E,在上面的代码里也就是Integer。
//输入case
["MinStack","push","push","push","min","pop","top","min"]
[[],[-2],[0],[-3],[],[],[],[]]
//我的输出
[null,null,null,null,-3,null,0,-2]
//完美符合 预期
但是在提交的时候发现通过不了,具体的case为:
//输入
["MinStack","push","push","push","push","pop","min","pop","min","pop","min"]
[[],[512],[-1024],[-1024],[512],[],[],[],[],[],[]]
//我的输出
[null,null,null,null,null,null,-1024,null,-1024,null,-1024]
//预期的输出应该为:
[null,null,null,null,null,null,-1024,null,-1024,null,512]
//看输出 应该是在最后一个pop的时候出现了问题
经过一番分析发现,和上面说的getLast方法有关系,在java中,存在着自动装箱拆箱的操作,具体可参看这个文章:
自动装箱
简单来说在值 为i < 128 && i >= -128 的时候直接返回的是已创建好的对象,而当超出这个范围的时候会创建不同的对象,因此在输入为-1024的时候 stack.getLast() == record.getLast() 是不会为true的
知道了原因之后,改起来也就很容易了,只需要拿到E的值,用这个值去判断就可以了。在JDK1.5 之后,可直接使用 int i = stack.getLast(); 自动拆箱