栈队列类编程题目

1 . 用两个栈实现队列

用两个栈来实现一个队列,完成队列的Push和Pop操作。 队列中的元素为int类型。

思路:用stack2用于输出,每次存入stack1,当要输入时,倒入到stack2。

代码

class Solution
{
public:
    void push(int node) {
        stack1.push(node);
    }
    int pop() {
        if(stack2.empty())
        {
            while(!stack1.empty())
            {
                stack2.push(stack1.top());
                stack1.pop();//明确出栈和取栈顶元素的区别
            }
        }
        int p = stack2.top();//可能需要抛出一个异常,如果stack2还为空的话
        stack2.pop();
        return p;
    }
private:
    stack<int> stack1;
    stack<int> stack2;
};

2. 包含mini函数的栈

定义栈的数据结构,请在该类型中实现一个能够得到栈中所含最小元素的min函数(时间复杂度应为O(1))。

思路
考虑使用两个栈一个数据栈,等同于普通的栈,实现push pop peek 等操作;另一个辅助栈实现min函数。
当两个栈为空时,push进去的第一个值即为最小值;
push第二个元素时,若push的值<辅助栈顶元素(此处即第一个值),则将此值压进辅助栈;若push的值大于等于辅助栈顶元素,则将辅助栈顶元素再次push进去。
pop的时候,数据栈辅助栈均弹出顶元素。

代码:

class Solution {
public:
    stack<int> s1,s2;
    void push(int value) {
        s1.push(value);
        if(s2.empty()) s2.push(value);
        else
        {
            int t = s2.top();
            s2.push(value > t ? t:value);
        }
    }
    void pop() {
        if(!s1.empty()) s1.pop();
        if(!s2.empty()) s2.pop();
    }
    int top() {
        if(!s1.empty())  return s1.top();
        return -1;
    }
    int min() {
        if(!s2.empty())  return s2.top();
        return -1;
    }
};

3. 栈的压入和弹出序列

输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压栈序列对应的一个弹出序列,但4,3,5,1,2就不可能是该压栈序列的弹出序列。(注意:这两个序列的长度是相等的)

思路
借用一个辅助的栈,遍历压栈顺序,先讲第一个放入栈中,这里是1,然后判断栈顶元素是不是出栈顺序的第一个元素,这里是4,很显然1≠4,所以我们继续压栈,直到相等以后开始出栈,出栈一个元素,则将出栈顺序向后移动一位,直到不相等,这样循环等压栈顺序遍历完成,如果辅助栈还不为空,说明弹出序列不是该栈的弹出顺序。

举例

入栈1,2,3,4,5

出栈4,5,3,2,1

首先1入辅助栈,此时栈顶1≠4,继续入栈2

此时栈顶2≠4,继续入栈3

此时栈顶3≠4,继续入栈4

此时栈顶4=4,出栈4,弹出序列向后一位,此时为5,,辅助栈里面是1,2,3

此时栈顶3≠5,继续入栈5

此时栈顶5=5,出栈5,弹出序列向后一位,此时为3,,辅助栈里面是1,2,3

….

依次执行,最后辅助栈为空。如果不为空说明弹出序列不是该栈的弹出顺序。

代码

class Solution {
public:
    bool IsPopOrder(vector<int> pushV,vector<int> popV) {
        if(pushV.size() == 0 || popV.size() == 0)
            return false;
        stack<int> s;
        int index = 0;
        for(int i = 0; i < pushV.size(); i ++)
        {
            s.push(pushV[i]);
            while(!s.empty() && s.top() == popV[index])
            {
                s.pop();
                index ++;
            }
        }
        return s.empty();
    }
};

4. 括号序列

给出一个仅包含字符’(’,’)’,’{’,’}’,’[‘和’]’,的字符串,判断给出的字符串是否是合法的括号序列
括号必须以正确的顺序关闭,"()“和”()[]{}“都是合法的括号序列,但”(]“和”([)]"不合法。

代码

class Solution {
public:
    /**
     * 
     * @param s string字符串 
     * @return bool布尔型
     */
    bool isValid(string s) {
        // write code here
        stack<char> stk;
        for(int i = 0; i < s.length(); i ++)
        {
            if(s[i] == '(' || s[i] == '{' || s[i] == '[')
                stk.push(s[i]);
            if(s[i] == ')')
            {
                if(!stk.empty() && stk.top() == '(')
                {
                    stk.pop();
                    continue;
                }
                else
                    return false;
            }
            if(s[i] == '}')
            {
                if(!stk.empty() && stk.top() == '{')
                {
                    stk.pop();
                    continue;
                }
                else
                    return false;
            }
            if(s[i] == ']')
            {
                if(!stk.empty() && stk.top() == '[')
                {
                    stk.pop();
                    continue;
                }
                else
                    return false;
            }
        }
        return stk.empty();
    }
};

5. 数据流中的中位数

如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。我们使用Insert()方法读取数据流,使用GetMedian()方法获取当前读取数据的中位数。

思路:
我们注意到当数据保存到容器中时,可以分为两部分,左边一部分的数据要比右边一部分的数据小。如下图所示,P1是左边最大的数,P2是右边最小的数,即使左右两部分数据不是有序的,我们也有一个结论就是:左边最大的数小于右边最小的数。
在这里插入图片描述

因此,我们可以有如下的思路:用一个最大堆实现左边的数据存储,用一个最小堆实现右边的数据存储,向堆中插入一个数据的时间是O(logn),而中位数就是堆顶的数据,只需要O(1)的时间就可得到。
  而在具体实现上,首先要保证数据平均分配到两个堆中,两个堆中的数据数目之差不超过1,为了实现平均分配,可以在数据的总数目是偶数时,将数据插入最小堆,否则插入最大堆。

代码

class Solution {
public:
    priority_queue<int, vector<int>, less<int>> left;
    priority_queue<int, vector<int>,greater<int>> right;
    void Insert(int num)
    {
        if(left.empty() || left.top() > num)
            left.push(num);
        else
            right.push(num);
        if(right.size()+2 == left.size())
        {
            right.push(left.top());
            left.pop();
        }
        if(left.size()+1 == right.size())
        {
            left.push(right.top());
            right.pop();
        }
    }

    double GetMedian()
    { 
       return (right.size() == left.size())? (right.top()+left.top())/2.0: left.top();
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值