解题思路
题干要求取最小值的时间复杂度是常数级,正常取一个数组中的最小值需要O(n)的复杂度,即每个元素比较一次。
····这里选用数组a来存储栈····
#方法一:哈希查找
要想减小时间复杂度,最方便的方法就是空间换时间,要么利用哈希给每个元素标号,就是维护一个序号数组大小 由最大元素值和最小元素值大小而定,即max(x)-min(x)的大小(负数的话就要用两个哈希数组,一个表示正,一个表示负)每个元素值下内容是每个元素的排名,但是仔细想来,出栈的时候要遍历元素范围那么大复杂度的数组,然后每个排名都减一,当然如果数据整体取值的范围远小于个数n(比如10000个数,都在0-30之间),那么这种方法就效率很高。最后取最小值就是遍历这两个数组,找到下标为1的那个索引即时所求。
#方法二:维护动态有序数组
这个方法就像STL里的set序列一样,每次插入元素都将其递增排序,每次删除元素都把该动态数组将其按插入排序删除元素的思想向前覆盖,这样该数组的0号位置的元素一直都是最小值,就实现了常数级查找最小值
两种方法的区别:
看数据的类型 ->如果数量n远大于数的范围就选用哈希方法 ->如果数量n远小于数的范围就选用维护数组的方法
-------------------- !谢谢各位大佬阅读,感谢评论指点。代码
class MinStack {
int MinElement[100000];
int a[100000];
int len;
public:
/** initialize your data structure here. */
MinStack() {
len = 0;
}
void push(int x) {
a[len++] = x;
if(len == 1) MinElement[0] = x;
else{
for(int i=len-2;i>=0;i--){
//从开始比较到插入需要n+1次,插入时还需要一次比较,大于x元素移动次数插入判别加1次。所以当 //所有元素都大于x时,循环已经结束,但是x还未插入、
if(MinElement[i]>=x){
MinElement[i+1] = MinElement[i];
}else{
MinElement[i+1] = x;
break;
}
if(i == 0){
MinElement[0] = x;
}
}
}
}
void pop() {
int flag=0,top = a[len-1];
for(int i=0;i<len;i++){
if(MinElement[i] == top){
flag=1;
continue;
}
if(flag){
MinElement[i-1] = MinElement[i];
}
}
len--;
}
int top() {
return a[len-1];
}
int getMin() {
return MinElement[0];
}
};
/**
* 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->getMin();
*/
突然发现官方那个双栈也不错,有序栈维护每个元素对应的当前最小值,如果添加元素小于当前最小,那么就再push一个当前最小元素,然后同时出栈。巧妙…