1.用两个栈实现队列
当Stack2不为空时,在stack2的栈顶元素是最先进入队列的元素,可以弹出。当stack2为空时,我们把stack1中的元素逐个弹出并压入stack2.
push操作的话比较简单,直接往stack1里面push. pop操作的话,如果stack2不空的话,出元素;如果stack2为空的话,把stack1中的元素全部压入,然后出。可以举例子来分析这个过程
最大的容量是2P+1,其中P<O
class Solution
{
public:
void push(int node) {
stack1.push(node);
}
int pop() {
if(stack2.size()<=0){//这句是必不可少的,试想如果没有这个条件判断,则会发生stack2本来有元素可以弹出,但是又把新的元素压进来了弹出的元素就是错的了
while(!stack1.empty()){
stack2.push(stack1.top());
stack1.pop();
}
}
int res=stack2.top();
stack2.pop();
return res;
}
private:
stack<int> stack1;
stack<int> stack2;
};
相关问题:用两个队列实现一个栈
用两个队列,当要弹出元素的时候,就把queue1的前n-1个元素都先放到queue2,这时候就只剩下这一个元素了从队列的头部出来。
q.pop() front back
2.包含min函数的栈
题目:定义栈的数据结构,请在该类型中实现一个能够得到栈的最小元素的min函数。
会比较容易想到,添加一个成员变量存放最小的元素,每次压入一个新元素进栈的时候,如果该元素比当前最小的元素还要小,则更新最小元素
但是如果当前最小的元素被弹出栈了,那么如何得到下一个最小的元素呢?因此,在压入这个最小元素之前,我们要把次小元素保存起来。
class MinStack {
stack<int> data;
stack<int> helper;
public:
/** initialize your data structure here. */
MinStack() {
helper.push(INT_MAX);
}
void push(int x) {
data.push(x);
int temp=helper.top();
if(x<temp) helper.push(x);
else helper.push(temp);
}
void pop() {
data.pop();
helper.pop();
}
int top() {
return data.top();
}
int min() {
return helper.top();
}
};
/**
* 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();
*/
3.面试题31:栈的压入,弹出序列
输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出序列。假设压入栈的所有数字均不相等。
我们可以找出判断一个序列是不是栈的弹出序列的规律:如果下一个弹出的数字刚好是栈顶数字,那么直接弹出;如果下一个弹出的数字不在栈顶,则把压栈序列中还没有入栈的数字压入辅助栈,知道把下一个需要弹出的数字压入栈顶为止;如果所有元素都压入栈了仍然没有找到下一个弹出的元素,那么该序列不可能是一个弹出序列。
终于靠着分析条件判断的逻辑把这个题目写出来了,昨晚一直卡着,注意栈为空的逻辑:此刻是一定可以压入元素的,不然while循环执行不到这一步的。
class Solution {
public:
int findtarget(vector<int>& pushed,int target){
vector<int>::iterator it=find(pushed.begin(),pushed.end(),target);
return it-pushed.begin();
}
bool validateStackSequences(vector<int>& pushed, vector<int>& popped) {
if(pushed.empty()) return true;
stack<int> m;
int p=0;//p用来记录压入序列中的位置,压到哪里了
int n=pushed.size();
int i=0;//i是指针
int index;
bool res=true;
while(i<n){
int elem=popped[i];
if(m.empty()){
index=findtarget(pushed,elem);
if(index>=p){
for(int j=p;j<=index;++j){
m.push(pushed[j]);
++p;
}
m.pop();
}
}
else{//栈不空
if(elem==m.top()){
m.pop();
}
else{//跟栈顶元素不同
index=findtarget(pushed,elem);
if(index<p){//不能压入
return false;
}
else{//可以压入
for(int j=p;j<=index;++j){
m.push(pushed[j]);
++p;
}
m.pop();
}
}
}
++i;
}
return true;
}
};
4.合并两个有序数组
只做了初步测试的代码:这里需要明白,需要三个指针(所以我们还需要第三个指针以便复制)。需要一个指针p来定位新排列的数组。其实跟合并两个有序链表有区别也有联系,要多分析问题,思考
int main()
{
int aLength,bLength;
cin>>aLength>>bLength;
int a[aLength+bLength];
int b[bLength];
for(int i=0;i<aLength;++i)
cin>>a[i];
for(int i=0;i<bLength;++i)
cin>>b[i];
int p1=aLength-1;
int p2=bLength-1;
int p=aLength+bLength-1;
while(p2>=0&&p1>=0){
if(b[p2]>a[p1]){
a[p]=b[p2];
p--;
p2--;
}
else{
a[p]=a[p1];
p--;
p1--;
}
}
if(p1<0){
while(p2>=0){
a[p]=b[p2];
p2--;
p--;
}
}
for(int i=0;i<aLength+bLength;++i){
cout<<a[i]<<" ";
}
//cout << "Hello world!" << endl;
return 0;
}
上面的代码实际上还有缺陷,而且没有经过充分的测试,考虑数组1的长度为0的情况,这是在力扣上测试的。
class Solution {
public:
void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
int p1=m-1, p2=n-1;
int p=m+n-1;
while(p1>=0 && p2>=0){
if(nums1[p1]>=nums2[p2]){
nums1[p]=nums1[p1];
--p1;
--p;
}
else{
nums1[p]=nums2[p2];
--p2;
--p;
}
}
while(p2>=0){
nums1[p]=nums2[p2];
--p2;
--p;
}
}
};