这个系列是记录我刷《剑指Offer》这套题的过程,主要还是精刷,我的目的是能尽可能的用最优的方法解决和尽可能地把算法思路说明白。
用两个栈实现队列
用两个栈实现一个队列。队列的声明如下,请实现它的两个函数 appendTail 和 deleteHead ,分别完成在队列尾部插入整数和在队列头部删除整数的功能。(若队列中没有元素,deleteHead 操作返回 -1 )
示例 1:
输入:
["CQueue","appendTail","deleteHead","deleteHead"]
[[],[3],[],[]]
输出:[null,null,3,-1]
示例 2:
输入:
["CQueue","deleteHead","appendTail","appendTail","deleteHead","deleteHead"]
[[],[],[5],[2],[],[]]
输出:[null,-1,null,null,5,2]
提示:
1 <= values <= 10000 最多会对 appendTail、deleteHead 进行 10000 次调用
解法一:
class CQueue {
public:
stack<int> a, b;
CQueue() {
}
void appendTail(int value) {
while(a.empty() != true){
b.push(a.top());
a.pop();
}
a.push(value);
while(b.empty() != true){
a.push(b.top());
b.pop();
}
}
int deleteHead() {
if(a.empty())return -1;
int ans = a.top();
a.pop();
return ans;
}
};
/**
* Your CQueue object will be instantiated and called as such:
* CQueue* obj = new CQueue();
* obj->appendTail(value);
* int param_2 = obj->deleteHead();
*/
解法思路:
因为有两个栈,所以可以让一个栈在特定位置插入元素且不改变原栈内其它元素的次序,方法是将x 个元素先从一个栈apop 并push 进另外一个栈b,将新元素push 进栈a后再将栈b的所有元素pop 并push 进栈a,这就完成了栈a内元素的按顺序插入。
因此队列(FIFO)的push 实现可以是每次将新元素存入栈a的头部,pop 则是栈a的直接pop 。每次push 时,先将栈a的所有元素存进栈b,向栈apush 进新元素后,再把栈b中的元素push 进栈a,这就完成了队列的插入。
解法二:
class CQueue {
public:
stack<int> a, b;
CQueue() {
}
void appendTail(int value) {
a.push(value);
}
int deleteHead() {
if(b.empty()){
if(a.empty())return -1;
while(a.empty() == false){
b.push(a.top());
a.pop();
}
}
int ans = b.top();
b.pop();
return ans;
}
};
解法思路
解法一非常容易想到,但也存在很多不足,每次CQueue 的push 操作都有两个栈的清空和填充,这是极浪费时间和没有必要的,我们再细想队列的特性,只有两个重要的结点,就是头和尾,我们可以用一个栈维护一个结点,也可以说是两个栈组成一个队列,就如下面的图(画得有亿点丑)
大概就是这样,s2 是队列的入口,s1 是出口,每次弹出时先检查s1 是否为空,不为空直接弹出,空的话将s2 的元素弹入s1 ,这样就避免了像解法一一样做很多无用的维护。
包含min函数的栈
定义栈的数据结构,请在该类型中实现一个能够得到栈的最小元素的 min 函数在该栈中,调用 min 、push 及 pop 的时间复杂度都是 O(1) 。
示例:
MinStack minStack = new MinStack();
minStack.push(-2);
minStack.push(0);
minStack.push(-3);
minStack.min(); --> 返回 -3.
minStack.pop();
minStack.top(); --> 返回 0.
minStack.min(); --> 返回 -2.
提示:
class MinStack {
public:
/** initialize your data structure here. */
int n;
vector<int> minn;
stack<int> s;
MinStack() {
n = 0;
minn.resize(20005);
}
void push(int x) {
minn[n] = s.empty() ? x : ::min(x, minn[n - 1]);
s.push(x);
n ++;
}
void pop() {
s.pop();
n --;
}
int top() {
return s.top();
}
int min() {
return minn[n - 1];
}
};
解法思路
这一题比较容易,就是记录每个结点所要的最小值,可以用栈存储,也可以直接用数组加指针,任何在栈弹出元素时指针前移即可。
最后
第一天的题还是比较简单的,都是考察栈的应用,都是简单题,希望我的博客能对你有所帮助。
新人博主发博,恳请各位不吝赐教,不胜感激,晚安。
题目链接: 用两个栈实现队列 包含min函数的栈
|