剑指offer:用两个栈实现队列+包含min函数的栈+栈的压入,弹出序列+合并两个有序数组

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;
                }
            
        }
};

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值