首页 > 其他分享 >6 栈与队列

6 栈与队列

时间:2023-07-24 16:15:13浏览次数:24  
标签:队列 pop int que result push

栈与队列

1 栈与队列基础

  • 栈:先进后出
    img

    • 栈是以底层容器完成其所有的工作,对外提供统一的接口,底层容器是可插拔的(也就是说我们可以控制使用哪种容器来实现栈的功能)。
    • 我们常用的SGI STL,如果没有指定底层实现的话,默认是以deque为缺省情况下栈的底层结构。

2 用栈实现队列

题目:

使用栈实现队列的下列操作:
push(x) -- 将一个元素放入队列的尾部。
pop() -- 从队列首部移除元素。
peek() -- 返回队列首部的元素。
empty() -- 返回队列是否为空。

思路:

两个栈 stkIn和stkOut

  • push():stkIn.push()
  • pop():stkIn中的元素push到stkOut中,stkOut.pop()
  • peek():利用pop,弹出后再压回到stkOut中
  • empty():stkIn和stkOut都为空则空

代码:

stack<int> stkIn;
stack<int> stkOut;
MyQueue() {

}

void push(int x) {
    stkIn.push(x);
}

int pop() {
    if(stkOut.empty()){
        while(!stkIn.empty()){
            stkOut.push(stkIn.top());
            stkIn.pop();
        }
    }
    int result = stkOut.top();
    stkOut.pop();
    return result;
}

int peek() {
    int result = this->pop();
    stkOut.push(result);
    return result;
}

bool empty() {
    return stkIn.empty()&&stkOut.empty();
}

3 队列实现栈

题目:

使用队列实现栈的下列操作:

push(x) -- 元素 x 入栈
pop() -- 移除栈顶元素
top() -- 获取栈顶元素
empty() -- 返回栈是否为空

思路:

一个队列即可实现模拟栈

代码:

queue<int>que;
MyStack() {

}

void push(int x) {
    que.push(x);
}

int pop() {
    int size = que.size();
    while(size>1){
        que.push(que.front());
        que.pop();
        size--;
    }
    int result = que.front();
    que.pop();
    return result;
}

int top() {
    return que.back();
}

bool empty() {
    return que.empty();
}

4 有效的括号

题目:

给定一个只包括 '(',')','{','}','[',']' 的字符串,判断字符串是否有效。

有效字符串需满足:

左括号必须用相同类型的右括号闭合。
左括号必须以正确的顺序闭合。
注意空字符串可被认为是有效字符串。

思路:

定义一个栈,检测到括号就压入,遇到对应的消除,出现错误就返回无效,最后栈不为空也是无效

代码:

bool isValid(string s) {
        if (s.size() % 2 != 0) return false; 
        stack<char> st;
        for(int i=0;i<s.size();i++){
            if(s[i]=='(' || s[i]=='{' || s[i]=='['){
                st.push(s[i]);
            }
            else if(s[i]==')' && !st.empty() && st.top()=='(') st.pop();
            else if(s[i]==']' && !st.empty() && st.top()=='[') st.pop();
            else if(s[i]=='}' && !st.empty() && st.top()=='{') st.pop();
            else return false;
        }
        if(!st.empty()) return false;
        return true;
}

5 删除字符串中的所以后相邻重复项

题目:

给出由小写字母组成的字符串 S,重复项删除操作会选择两个相邻且相同的字母,并删除它们。

在 S 上反复执行重复项删除操作,直到无法继续删除。

在完成所有重复项删除操作后返回最终的字符串。答案保证唯一。

思路:

反复跟栈顶元素对比即可

这里可以把string当作栈,这样少一次颠倒的操作

代码:

string removeDuplicates(string s) {
    string result;
    for(int i=0;i<s.size();i++){
        if(result.empty() || s[i]!=result.back()){
            result.push_back(s[i]);
        }
        else{
            result.pop_back();
        }
    }
    return result;
}

6 逆波兰表达式求值

题目:

根据 逆波兰表示法,求表达式的值。

思路:

挨个入栈,遇到计算符,开始pop前两个元素进行计算,最后只剩一个元素就是结果

代码:

int evalRPN(vector<string>& tokens) {
    stack<long long>pld;
    for(int i=0;i<tokens.size();i++){
        if(tokens[i]=="+" || tokens[i]=="-" || tokens[i]=="*" || tokens[i]=="/")
        {
            long long num1=pld.top();
            pld.pop();
            long long num2=pld.top();
            pld.pop();
            if(tokens[i] == "+") pld.push(num2 + num1);
            if(tokens[i] == "-") pld.push(num2 - num1);
            if(tokens[i] == "*") pld.push(num2 * num1);
            if(tokens[i] == "/") pld.push(num2 / num1);
        }
        else {
            pld.push(stoll(tokens[i]));
        }
    }
    int result = pld.top();
    pld.pop();
    return result;
}

注意:

  • longlong定义
  • stoll:string to longlong
  • 注意是num2与num1运算

7 滑动窗口最大值

题目:

给定一个数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。

返回滑动窗口中的最大值。

思路:

定义一个class myQueue,维护单调队列,保存窗口内的单调性,front为最大值

代码:

class Solution {
private:
    class myQueue{
    public:
        deque<int> que;
        void pop(int num){
            if(!que.empty() && num == que.front()){
                que.pop_front();
            }
        }
        void push(int num){
            while(!que.empty() && num>que.back()){
                que.pop_back();
            }
            que.push_back(num);
        }
        int front(){
            return que.front();
        }
    };
public:
    vector<int> maxSlidingWindow(vector<int>& nums, int k) {
        myQueue que;
        vector<int>result;
        for(int i=0 ; i < k ; i++){
            que.push(nums[i]);
        }
        result.push_back(que.front());
        for(int i=k;i<nums.size();i++){
            que.pop(nums[i-k]);
            que.push(nums[i]);
            result.push_back(que.front());
        }
        return result;
    }
};

难点在于时间复杂度为O(n),暴力算法复杂度为O(k * n),要不断在窗口内求最大值。

8 前k个高频元素

题目:

给定一个非空的整数数组,返回其中出现频率前 k 高的元素。

思路:

优先级队列priority_queue,

代码:

class Solution {
public:
    // 小顶堆
    class mycomparison {
    public:
        bool operator()(const pair<int, int>& lhs, const pair<int, int>& rhs) {
            return lhs.second > rhs.second;
        }
    };
    vector<int> topKFrequent(vector<int>& nums, int k) {
        // 要统计元素出现频率
        unordered_map<int, int> map; // map<nums[i],对应出现的次数>
        for (int i = 0; i < nums.size(); i++) {
            map[nums[i]]++;
        }

        // 对频率排序
        // 定义一个小顶堆,大小为k
        priority_queue<pair<int, int>, vector<pair<int, int>>, mycomparison> pri_que;

        // 用固定大小为k的小顶堆,扫面所有频率的数值
        for (unordered_map<int, int>::iterator it = map.begin(); it != map.end(); it++) {
            pri_que.push(*it);
            if (pri_que.size() > k) { // 如果堆的大小大于了K,则队列弹出,保证堆的大小一直为k
                pri_que.pop();
            }
        }

        // 找出前K个高频元素,因为小顶堆先弹出的是最小的,所以倒序来输出到数组
        vector<int> result(k);
        for (int i = k - 1; i >= 0; i--) {
            result[i] = pri_que.top().first;
            pri_que.pop();
        }
        return result;

    }
};

标签:队列,pop,int,que,result,push
From: https://www.cnblogs.com/mobbu/p/17577474.html

相关文章

  • .net消息队列
    .NET消息队列消息队列是一种常用的软件架构模式,可以实现异步通信和解耦合。在分布式系统中使用消息队列可以提高系统的可伸缩性和可靠性。.NET框架提供了一个称为.NET消息队列(.NETMessageQueue,简称MSMQ)的组件,用于在应用程序之间发送消息。什么是.NET消息队列?.NET消息队列是一......
  • 【优先队列】【堆排序实现优先队列】[1054. 距离相等的条形码](https://leetcode.cn/p
    【优先队列】【堆排序实现优先队列】1054.距离相等的条形码在一个仓库里,有一排条形码,其中第i个条形码为barcodes[i]。请你重新排列这些条形码,使其中任意两个相邻的条形码不能相等。你可以返回任何满足该要求的答案,此题保证存在答案。示例1:输入:barcodes=[1,1,1,2,2,2]......
  • day10 栈与队列
    232.用栈实现队列题解:这一题在大学的时候学过,用两个栈来实现队列,队列是先进先出,而栈是先进后出,所以需要两个栈一个用来存队列入队的数据,出队列的时候,需要将顺序调转,这时候就需要用到另一个队列,注意好边界条件就行225.用队列实现栈题解:队列实现栈的功能也不难,主要是想到栈......
  • python 实现队列
    Python实现队列引言在计算机科学中,队列是一种常见的数据结构,用于存储和管理元素。队列采用先进先出(FIFO)的原则,即最先进入队列的元素最先被处理。在Python中,可以使用列表和相关的操作来实现队列。本文将介绍如何使用Python实现队列,并提供详细的代码示例和解释。实现步骤下表展......
  • 一个故事告诉你什么是消息队列
    有一天,产品跑来说:“我们要做一个用户注册功能,需要在用户注册成功后给用户发一封成功邮件。”小明(攻城狮):“好,需求很明确了。”不就提供一个注册接口,保存用户信息,同时发起邮件调用,待邮件发送成功后,返回用户操作成功。没一会功夫,代码就写完了。验证功能没问题后,就发布上线了。线上......
  • php与 redis的队列 && 如何守护进程?
    在PHP中,使用队列可以解决以下情况下的一些常见问题:异步任务处理:当应用程序需要处理一些耗时的任务,如发送电子邮件、生成报表、处理文件上传等,可以将这些任务添加到队列中,并使用队列进行异步处理,从而不影响主要的用户请求处理。消息通信:在分布式系统或微服务......
  • leetcode 栈与队列 232 225
    目录基本介绍四个问题232225基本介绍栈,先进后出队列,先进先出四个问题C++中stack是容器么?我们使用的stack是属于哪个版本的STL?我们使用的STL中stack是如何实现的?stack提供迭代器来遍历stack空间么?首先大家要知道栈和队列是STL(C++标准库)里面的两个数据结构。C++标准......
  • 深入理解队列
    理解队列:从生活中的排队到计算机的数据结构队列(Queue)是计算机科学中一种常见的数据结构,它在计算机程序和算法中扮演着重要角色。然而,队列的概念并不仅仅局限于计算机领域,我们在日常生活中也能够轻松地找到许多队列的例子。本文将介绍队列的基本概念、实现方式以及它在计算机科学......
  • 队列的具体实现方式
    队列可以通过两种常见的实现方式来表示:顺序队列(数组实现)和链式队列(链表实现)。这两种方式在计算机科学中都广泛使用,每种实现方式都有其优势和适用场景。1.顺序队列(数组实现):顺序队列是使用数组来表示队列的一种实现方式。在顺序队列中,我们使用一个固定大小的数组来存储队列的元素......
  • c++环形队列的简单实现
    环形队列可以通过维护count来间接维护tail和head指针的关系,简化程序,避免了直接使用tail和head指针,读写时head与tail回环时的比较处理,判断队列元素长度时的复杂处理,如下为不基于count而是直接使用head和tail指针比较的环形队列的实现,逻辑较为复杂uint32_tCAudioRingBuffer::Da......