设计一个支持 push,pop,top 操作,并能在常数时间内检索到最小元素的栈。
push(x) – 将元素 x 推入栈中。
pop() – 删除栈顶的元素。
top() – 获取栈顶元素。
getMin() – 检索栈中的最小元素。
首先使用STL库 stack,有两种思路
1.用两个栈来记录,一个记录所有的值,一个只记录最小值,
push——第一个栈所有都push,第二栈只push和当前一样或者比当前小的值
pop的时候如果第一个栈和第二个栈的数字相等,两个都执行pop,否则只pop第二个
2.第一个思路的优化版本,只用一个栈,和一个int
在每一次push min value的时候,多插一次上一次的值,
在每一次pop 的时候如果 pop的是最小值,那么就用一下个当做最小值,病且也把这个值pop出去。
可以参考这个人的博客
https://www.cnblogs.com/lightwindy/p/8512214.html
下面是我的思路:
用了一个数组来创建最小堆, 用链表管理他们直接的循序,比较复杂有兴趣的可以看一下,如果有什么建议可以留言给我
class MinStack {
public:
/** initialize your data structure here. */
/** 最小栈里面不仅仅需要存数据,还要动态的存他们在这个数组中的位置 */
struct Info{
int data;
int pos;
};
//一个链表模拟一个栈,每一个节点上记录了一个最小堆上元素的地址,
//这样做的目的是
struct LinkNode{
Info *ptr;
LinkNode* next;
LinkNode(Info* _pos) : ptr(_pos), next(NULL){}
};
LinkNode *head;
vector<Info*> stack;
MinStack() :head(NULL) {
}
~MinStack(){
//释放内存
while(head != NULL){
LinkNode* t = head;
head = head -> next;
delete t;
}
}
void push(int x) {
//插入到最小堆中,放到最后
Info *info = new Info();
info->data = x;
stack.push_back(info);
int pos = stack.size() - 1;
//向上开始整理堆,保证堆顶元素最小
int f = pos % 2 == 0 ? (pos - 2) / 2 : (pos - 1) / 2;
while (f >= 0 && stack[pos]->data < stack[f]->data){
stack[f]->pos = pos; //动态的改变 节点上的位置信息, father节点的位置要向下移
Info* temp = stack[pos]; stack[pos] = stack[f]; stack[f] = temp; //注意这里交换的是地址!!!
pos = f;
f = pos % 2 == 0 ? (pos - 2) / 2 : (pos - 1) / 2; //计算心father
}
info->pos = pos;
//update 链表
LinkNode* node = new LinkNode(info);
node->next = head;
head = node;
}
void pop() {
if (head == NULL) return;
int pos = head->ptr->pos;
//exchange with the last one
int last = stack.size() - 1;
//交换当前移除堆的元素 和 堆底的元素 准备调整堆
Info* temp = stack[pos]; stack[pos] = stack[last]; stack[last] = temp;
stack[pos]->pos;
stack.pop_back();
//移除链表 释放内存
LinkNode* t = head; head = head->next;
delete t;
//向下调整堆
while (pos * 2 + 1 < stack.size() || pos * 2 + 2 < stack.size()){
if (pos * 2 + 2 < stack.size()){
if (stack[pos * 2 + 2]->data < stack[pos * 2 + 1]->data){
if (stack[pos]->data > stack[pos * 2 + 2]->data){
Info* temp = stack[pos]; stack[pos] = stack[pos * 2 + 2]; stack[pos * 2 + 2] = temp;
stack[pos]->pos = pos; stack[pos * 2 + 2]->pos = pos * 2 + 2;
pos = pos * 2 + 2;
}
else break;
}
else{
if (stack[pos]->data > stack[pos * 2 + 1]->data){
Info* temp = stack[pos]; stack[pos] = stack[pos * 2 + 1]; stack[pos * 2 + 1] = temp;
stack[pos]->pos = pos; stack[pos * 2 + 1]->pos = pos * 2 + 1;
pos = pos * 2 + 1;
}
else break;
}
}
else if (pos * 2 + 1 < stack.size()){
if (stack[pos]->data > stack[pos * 2 + 1]->data){
Info* temp = stack[pos]; stack[pos] = stack[pos * 2 + 1]; stack[pos * 2 + 1] = temp;
stack[pos]->pos = pos; stack[pos * 2 + 1]->pos = pos * 2 + 1;
pos = pos * 2 + 1;
}
else break;
}
}
}
int top() {
return head->ptr->data;
}
int getMin() {
if (stack.size() == 0) return 0;
return stack[0]->data;
}
};