定义栈的数据结构,请在该类型中实现一个能够得到栈的最小元素的 min 函数在该栈中,调用 min、push 及 pop 的时间复杂度都是 O(1)。
模板:
/**
* initialize your data structure here.
*/
var MinStack = function() {
};
/**
* @param {number} x
* @return {void}
*/
MinStack.prototype.push = function(x) {
};
/**
* @return {void}
*/
MinStack.prototype.pop = function() {
};
/**
* @return {number}
*/
MinStack.prototype.top = function() {
};
/**
* @return {number}
*/
MinStack.prototype.min = function() {
};
/**
* Your MinStack object will be instantiated and called as such:
* var obj = new MinStack()
* obj.push(x)
* obj.pop()
* var param_3 = obj.top()
* var param_4 = obj.min()
*/
解题思路:
这道题要求的时间复杂度较小,我们可以考虑用空间换时间,创建一个辅助栈
- 数据栈stack1:用于存储所有元素,保证入栈push()函数、出栈pop()函数、获取栈顶top()函数的正常逻辑。
- 辅助栈stack2:用于存储数据栈stack1中所有的非严格降序的元素,则数据栈stack1中的最小元素始终对应辅助栈stack2的栈顶元素,即min()函数只需返回辅助栈stack2的栈顶元素即可。
只需让辅助栈中元素保持非严格降序,即可实现min()函数的O(1)复杂度。
函数设计:
- push(x)函数:重点为保持辅助栈stack2中的元素是非严格降序的。
1.将x压入数据栈stack1
2.若辅助栈stack2为空或者x小于等于辅助栈stack2的栈顶元素,则将x压入辅助栈stack2 - pop()函数:重点为保持数据栈和辅助栈的元素一致性。
1.执行数据栈stack1出栈,将出栈元素记为y
2.若y等于辅助栈stack2的栈顶元素,则执行stack2出栈 - top()函数:直接返回数据栈stack1的栈顶元素
- min()函数:直接返回辅助栈stack2的栈顶元素
复杂度分析:
- 时间复杂度O(1):push()、pop()、top()、min()四个函数的时间复杂度均为常数级别
- 空间复杂度O(N):当共有N个待入栈元素时,辅助栈stack2最差情况下存储N个元素,使用O(N)额外空间。
代码实现:
/**
* initialize your data structure here.
*/
var MinStack = function() {
this.stack1 = [];//数据栈
this.stack2 = [];//辅助栈
};
/**
* @param {number} x
* @return {void}
*/
MinStack.prototype.push = function(x) {
this.stack1.push(x); //元素压入数据栈
if(this.stack2.length == 0){//若辅助栈为空 直接压入
this.stack2.push(x);
}else{
if(this.stack2[this.stack2.length - 1] >= x){//若辅助栈栈顶元素大于等于该元素 即数据栈中最小值更新
this.stack2.push(x);
}
}
};
/**
* @return {void}
*/
MinStack.prototype.pop = function() {
var pop = this.stack1.pop();
if(pop == this.stack2[this.stack2.length - 1]){//若删除的元素等于辅助栈的栈顶元素 即该元素是数据栈中的最小值 要删除辅助栈栈顶元素 更新最小值
this.stack2.pop();
}
};
/**
* @return {number}
*/
MinStack.prototype.top = function() {//返回数据栈的栈顶元素
return this.stack1[this.stack1.length - 1];
};
/**
* @return {number}
*/
MinStack.prototype.min = function() {//返回数据栈中的最小值 即辅助栈的栈顶元素
return this.stack2[this.stack2.length - 1];
};
/**
* Your MinStack object will be instantiated and called as such:
* var obj = new MinStack()
* obj.push(x)
* obj.pop()
* var param_3 = obj.top()
* var param_4 = obj.min()
*/
不必担心那些没有压入辅助栈的元素会作为数据栈最小值需要被输出的情况
因为辅助栈用于存储数据栈中所有非严格降序的元素,也就是说数据栈删除的栈顶元素只要不等于辅助栈的栈顶元素,则这个元素之下(栈顶到栈底)肯定有比它更小的元素,故这个元素在被删除之前不会作为数据栈的最小元素输出