代码随想录 -- 栈和队列

文章目录

  • 栈实现队列
    • 描述
    • 题解
  • 用队列实现栈
    • 描述
    • 题解
  • 有效的括号
    • 描述
    • 题解
  • 删除字符串中的所有相邻重复项
    • 描述
    • 题解
  • 逆波兰表达式求值
    • 描述
    • 题解
  • 滑动窗口最大值
    • 描述
    • 题解:暴力
    • 题解:单调队列
  • 前 K 个高频元素
    • 描述
    • 题解

栈实现队列

题目链接

描述

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

push(x) – 将一个元素放入队列的尾部。
pop() – 从队列首部移除元素。
peek() – 返回队列首部的元素。
empty() – 返回队列是否为空。

示例:

MyQueue queue = new MyQueue();
queue.push(1);
queue.push(2);
queue.peek();  // 返回 1
queue.pop();   // 返回 1
queue.empty(); // 返回 false

说明:

你只能使用标准的栈操作 – 也就是只有 push to top, peek/pop from top, size, 和 is empty 操作是合法的。
你所使用的语言也许不支持栈。你可以使用 list 或者 deque(双端队列)来模拟一个栈,只要是标准的栈操作即可。
假设所有操作都是有效的 (例如,一个空的队列不会调用 pop 或者 peek 操作)。

题解

使用两个栈来模拟队列:
一个栈为入队栈,一个栈为出队栈
出队栈的top为队头,入队栈的top为队尾(存在)
入队直接放入入队栈
出队先判断出队栈是否为空,不为空直接pop,为空先将入队栈的元素加入出队栈,然后再pop

class MyQueue {
private:
    stack<int>sIn;
    stack<int>sOut;
public:
    MyQueue()=default;

    void push(int x) {
        sIn.push(x);
    }
    void pushSOut(){
        if(sOut.empty()){
            //空
            while (!sIn.empty()){
                sOut.push(sIn.top());
                sIn.pop();
            }
        }
    }
    int pop() {
        pushSOut();
        int result = sOut.top();
        sOut.pop();
        return result;
    }

    int peek() {
        pushSOut();
        return sOut.top();
    }

    bool empty() {
        return sIn.empty()&&sOut.empty();
    }
};

用队列实现栈

题目链接

描述

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

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

你只能使用队列的基本操作-- 也就是 push to back, peek/pop from front, size, 和 is empty 这些操作是合法的。
你所使用的语言也许不支持队列。 你可以使用 list 或者 deque(双端队列)来模拟一个队列 , 只要是标准的队列操作即可。
你可以假设所有操作都是有效的(例如, 对一个空的栈不会调用 pop 或者 top 操作)。

题解

class MyStack {
private:
    queue<int> qIn;
    queue<int> qOut;
    int count=0;
public:
    MyStack() = default;

    void push(int x) {
        qIn.push(x);
        count++;
    }

    void handle(int num) {
        while (num) {
            qOut.push(qIn.front());
            qIn.pop();
            num--;
        }
    }

    void OutToIn() {
        while (!qOut.empty()) {
            qIn.push(qOut.front());
            qOut.pop();
        }
    }

    int pop() {
        handle(count - 1);
        count--;
        int res = qIn.front();
        qIn.pop();
        OutToIn();
        return res;
    }

    int top() {
        handle(count - 1);
        int res = qIn.front();
        handle(1);
        OutToIn();
        return res;
    }

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

也可以不使用conut记录长度 因为count就是qIn的长度

#include<iostream>
#include<queue>

using namespace std;

class MyStack {
private:
    queue<int> qIn;
    queue<int> qOut;
public:
    MyStack() = default;

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

    void handle(int num) {
        while (num) {
            qOut.push(qIn.front());
            qIn.pop();
            num--;
        }
    }

    void OutToIn() {
        while (!qOut.empty()) {
            qIn.push(qOut.front());
            qOut.pop();
        }
    }

    int pop() {
        handle(qIn.size()-1);
        int res = qIn.front();
        qIn.pop();
        OutToIn();
        return res;
    }

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

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


int main() {
    /**
 * Your MyStack object will be instantiated and called as such:
 * MyStack* obj = new MyStack();
 * obj->push(x);
 * int param_2 = obj->pop();
 * int param_3 = obj->top();
 * bool param_4 = obj->empty();
 */
    return 0;
}

有效的括号

题目链接

描述

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

有效字符串需满足:

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

输入: “()”
输出: true
示例 2:

输入: “()[]{}”
输出: true
示例 3:

输入: “(]”
输出: false

题解

题倒是不难 不过边界情况要考虑清楚 处理清楚

class Solution {
public:
    bool isValid(string s) {
        stack<char>stk;
        for (const auto &item: s) {
            switch (item) {
                case '(':
                    stk.push(item);
                    break;
                case '{':
                    stk.push(item);
                    break;
                case '[':
                    stk.push(item);
                    break;
                case ')':
                case '}':
                case ']':
                    if(stk.empty())
                        return false;
                    char c = stk.top();
                    stk.pop();
                    if(!((item==')'&&c=='(')||(item=='}'&&c=='{')||(item==']'&&c=='[')))
                        return false;
            }
        }
        if (stk.empty())return true;
        return false;
    }
};

删除字符串中的所有相邻重复项

题目链接

描述

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

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

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

示例:

输入:“abbaca”
输出:“ca”
解释:例如,在 “abbaca” 中,我们可以删除 “bb” 由于两字母相邻且相同,这是此时唯一可以执行删除操作的重复项。之后我们得到字符串 “aaca”,其中又只有 “aa” 可以执行重复项删除操作,所以最后的字符串为 “ca”。
提示:

1 <= S.length <= 20000
S 仅由小写英文字母组成。

题解

class Solution {
public:
    string removeDuplicates(string s) {
        stack<char>stk;
        for (const auto &item: s) {
            if(stk.empty())stk.push(item);
            else{
                char last = stk.top();
                if (last == item)stk.pop();
                else stk.push(item);
            }
        }
        string result;
        while (!stk.empty()){
            result+=stk.top();
            stk.pop();
        }
        reverse(result.begin(),result.end());
        return result;
    }
};

逆波兰表达式求值

题目链接

描述

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

有效的运算符包括 + , - , * , / 。每个运算对象可以是整数,也可以是另一个逆波兰表达式。

说明:

整数除法只保留整数部分。 给定逆波兰表达式总是有效的。换句话说,表达式总会得出有效数值且不存在除数为 0 的情况。

示例 1:

输入: [“2”, “1”, “+”, “3”, " * "]
输出: 9
解释: 该算式转化为常见的中缀算术表达式为:((2 + 1) * 3) = 9
示例 2:

输入: [“4”, “13”, “5”, “/”, “+”]
输出: 6
解释: 该算式转化为常见的中缀算术表达式为:(4 + (13 / 5)) = 6
示例 3:

输入: [“10”, “6”, “9”, “3”, “+”, “-11”, " * ", “/”, " * ", “17”, “+”, “5”, “+”]

输出: 22

解释:该算式转化为常见的中缀算术表达式为:

((10 * (6 / ((9 + 3) * -11))) + 17) + 5       
= ((10 * (6 / (12 * -11))) + 17) + 5       
= ((10 * (6 / -132)) + 17) + 5     
= ((10 * 0) + 17) + 5     
= (0 + 17) + 5    
= 17 + 5    
= 22    

逆波兰表达式:是一种后缀表达式,所谓后缀就是指运算符写在后面。

平常使用的算式则是一种中缀表达式,如 ( 1 + 2 ) * ( 3 + 4 ) 。

该算式的逆波兰表达式写法为 ( ( 1 2 + ) ( 3 4 + ) * ) 。

逆波兰表达式主要有以下两个优点:

去掉括号后表达式无歧义,上式即便写成 1 2 + 3 4 + * 也可以依据次序计算出正确结果。

适合用栈操作运算:遇到数字则入栈;遇到运算符则取出栈顶两个数字进行计算,并将结果压入栈中。

题解

class Solution {
public:
    int evalRPN(vector<string> &tokens) {
        stack<long long> numbers;
        string flags = "+-*/";
        int len = tokens.size();
        for (int i = 0; i < len; ++i) {
            if (flags.find(tokens[i])==string::npos)
                numbers.push(stoll(tokens[i]));
            else {
                long long num1 = numbers.top();//右操作数
                numbers.pop();
                long long num2 = numbers.top();//左操作数
                numbers.pop();
                if (tokens[i] == "+")numbers.push(num2 + num1);
                else if (tokens[i] == "-")numbers.push(num2 - num1);
                else if (tokens[i] == "*")numbers.push(num2 * num1);
                else if (tokens[i] == "/")numbers.push(num2 / num1);
            }
        }
       
        return numbers.top();
    }
};

滑动窗口最大值

题目链接

描述

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

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

进阶:

你能在线性时间复杂度内解决此题吗?

在这里插入图片描述

题解:暴力

力扣超出时间限制,行不通,时间复杂度为O(k*n)

class Solution {
public:
    vector<int> maxSlidingWindow(vector<int>& nums, int k) {
        vector<int>v;
        for (int i = 0; i <= nums.size()-k; ++i) {
                int max = -10000;
            for (int j = i; j < i+k; ++j) {
                if (nums[j]>max)max=nums[j];
            }
            v.push_back(max);
        }
        return v;
    }
};

题解:单调队列

有难度的题目

class Solution {
private:
    class MyQueue{
    private:
        deque<int>dq;
    public:
        // 删除滑动窗口第一个元素 (滑动窗口后移)
        // 每次弹出的时候,比较当前要弹出的数值是否等于队列出口元素的数值,如果相等则弹出。
        // 同时pop之前判断队列当前是否为空。
        void pop(int value){
            if(!dq.empty()&&value==dq.front())
                dq.pop_front();
        }
        // 如果push的数值大于入口元素的数值,那么就将队列后端的数值弹出,直到push的数值小于等于队列入口元素的数值为止。
        // 这样就保持了队列里的数值是单调从大到小的了。
        void push(int value){
            while(!dq.empty()&&value>dq.back())
                dq.pop_back();
            dq.push_back(value);
        }
        // 查询当前队列里的最大值 直接返回队列前端也就是front就可以了。
        int front(){
            return dq.front();
        }
    };
public:
    vector<int> maxSlidingWindow(vector<int>& nums, int k) {
        MyQueue mq;
        vector<int>result;
        for (int i = 0; i < k; ++i)
            mq.push(nums[i]);
        result.push_back(mq.front());
        for (int i = k; i < nums.size(); ++i) {
            mq.pop(nums[i-k]);
            mq.push(nums[i]);
            result.push_back(mq.front());
        }
        return result;
    }
};

前 K 个高频元素

题目链接

描述

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

示例 1:

输入: nums = [1,1,1,2,2,3], k = 2
输出: [1,2]
示例 2:

输入: nums = [1], k = 1
输出: [1]
提示:

你可以假设给定的 k 总是合理的,且 1 ≤ k ≤ 数组中不相同的元素的个数。
题目数据保证答案唯一,换句话说,数组中前 k 个高频元素的集合是唯一的。
你可以按任意顺序返回答案。

题解

优先队列+map

class Solution {
public:
    vector<int> topKFrequent(vector<int>& nums, int k) {
        map<int,int>mp;
        for(int num:nums){
            if (mp.find(num)!=mp.end()){
                mp[num]++;
            }else{
                mp.insert(make_pair(num,1));
            }
        }
        priority_queue<pair<int,int>>pq;
        for(auto & it : mp) {
            pq.emplace(it.second, it.first);
        }
        
        vector<int>v;
        while (k--){
            v.push_back(pq.top().second);
            pq.pop();
        }
        return v;
    }
};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/441555.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

WPF开源的一款免费、开箱即用的翻译、OCR工具

前言 今天大姚给大家分享一款由WPF开源的、免费的&#xff08;MIT License&#xff09;、即开即用、即用即走的翻译、OCR工具&#xff1a;STranslate。 WPF介绍 WPF 是一个强大的桌面应用程序框架&#xff0c;用于构建具有丰富用户界面的 Windows 应用。它提供了灵活的布局、…

TCP包头、TCP为什么安全可靠、UDP和TCP的区别、http协议

我要成为嵌入式高手之3月8日Linux高编第十八天&#xff01;&#xff01; __________________________________________________ 学习笔记 TPC包头 1、序号 发送端发送数据包的编号 2、确认号 已经确认接收到的数据的编号&#xff0c;只有当ACK为1时&#xff0c;该位才有用 …

sentinel prometheus指标收集及资源规则正则表达式实现

sentinel 支持 prometheus 收集指标 实现原理 在 sentinel-extension 模块下&#xff0c;新增 sentinel-prometheus-metric-exporter 模块。依赖Prometheus 提供的 simpleclient 和 simpleclient_httpserver 来实现 exporter。 依赖 simpleclient 主要是为了实现自定义Collect…

关于手机是否支持h264的问题的解决方案

目录 现象 原理 修改内容 现象 开始以为是手机不支持h264的编码 。机器人chatgpt一通乱扯。 后来检查了下手机&#xff0c;明显是有h264嘛。 终于搞定&#xff0c;不枉凌晨三点起来思考 原理 WebRTC 默认使用的视频编码器是VP8和VP9&#xff0c;WebRTC内置了这两种编码器…

flink重温笔记(十二): flink 高级特性和新特性(1)——End-to-End Exactly-Once(端到端精确一致性语义)

Flink学习笔记 前言&#xff1a;今天是学习 flink 的第 12 天啦&#xff01;学习了 flink 高级特性和新特性之 End-to-End Exactly-Once&#xff08;端到端精确一致性语义&#xff09;&#xff0c;主要是解决大数据领域数据从数据源到数据落点的一致性&#xff0c;不会容易造成…

计算机组成原理之机器:存储器之辅助存储器

计算机组成原理之机器&#xff1a;存储器之辅助存储器 笔记来源&#xff1a;哈尔滨工业大学计算机组成原理&#xff08;哈工大刘宏伟&#xff09; Chapter3&#xff1a;存储器之辅助存储器 3.1 概述 3.2 磁记录原理 通不同方向电流时磁化方向不同&#xff0c;由此区分写入…

逆向分析 FSViewer 并写出注册机

逆向分析 FSViewer 并写出注册机 FSViewer是一款老牌的图片管理查看编辑软件, 个人使用免费, 商用收费 本文将逆向分析FSViewer 7.5版本的注册算法并编写注册机 0. 前言 最近在整理之前的资料, 发现了一篇几年前刚学逆向那会儿写的文章, 是跟着看雪一位大牛的文章做的, 但逆向…

基于yolov5的番茄检测系统,可进行图像目标检测,也可进行视屏和摄像检测(pytorch框架)【python源码+UI界面+功能源码详解】

功能演示&#xff1a; 基于yolov5的小番茄检测系统&#xff0c;系统既能够实现图像检测&#xff0c;也可以进行视屏和摄像实时检测_哔哩哔哩_bilibili &#xff08;一&#xff09;简介 基于yolov5的番茄检测系统是在pytorch框架下实现的&#xff0c;这是一个完整的项目&…

Vue 项目性能优化指南:提升应用速度与效率

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…

【前端】-初始前端以及html的学习

&#x1f496;作者&#xff1a;小树苗渴望变成参天大树&#x1f388; &#x1f389;作者宣言&#xff1a;认真写好每一篇博客&#x1f4a4; &#x1f38a;作者gitee:gitee✨ &#x1f49e;作者专栏&#xff1a;C语言,数据结构初阶,Linux,C 动态规划算法&#x1f384; 如 果 你 …

(未解决)macOS matplotlib 中文是方框

reference&#xff1a; Mac OS系统下实现python matplotlib包绘图显示中文(亲测有效)_mac plt 中文值-CSDN博客 module ‘matplotlib.font_manager‘ has no attribute ‘_rebuild‘解决方法_font_manager未解析-CSDN博客 # 问题描述&#xff08;笑死 显而易见 # solve 找到…

CleanMyMac X4.15.0专为macOS设计的清理和优化工具

CleanMyMac X 是一款专为 macOS 设计的清理和优化工具。其基本功能和特点主要包括&#xff1a; 系统清理&#xff1a;CleanMyMac X 可以扫描并清除 macOS 系统中的垃圾文件&#xff0c;如缓存、日志、无用的语言文件等&#xff0c;从而释放硬盘空间并提高系统性能。应用程序管…

贪心算法(greedy algorithm,又称贪婪算法)详解(附例题)

目录 基本思想一&#xff09;概念二&#xff09;找出全局最优解的要求三&#xff09;求解时应考虑的问题四&#xff09;基本步骤五&#xff09;贪心策略选择六&#xff09;实际应用 1.零钱找回问题2.背包问题3.哈夫曼编码4.单源路径中的Djikstra算法5.最小生成树Prim算法 基本…

备考银行科技岗刷题笔记(持续更新版)

银行考试计算机部分复习 IEEE 802.11的帧格式 1.1 IEEE 802.11是什么&#xff1f; 802.11是国际电工电子工程学会&#xff08;IEEE&#xff09;为无线局域网络制定的标准。目前在802.11的基础上开发出了802.11a、802.11b、802.11g、802.11n、802.11ac。并且为了保证802.11更…

【电工学笔记】上册第一、二章

电工学 上次考试败在了单位&#xff0c;这次单位 一定要记熟。 第一章 电源或信号源的电压或电流称为激励,它推动电路工作; 由激励所产生的电压和电流称为响应。 复杂电路中,一般无法事先判断某个支路电流的 实际方向或者某个电路元件电压的实际方向 140V/4算不出总电阻的 …

thingsboard如何自定义udp-transport

0、参考netty实现udp的文章 https://github.com/narkhedesam/Netty-Simple-UDP-TCP-server-client/blob/master/netty-udp/src/com/sam/netty_udp/server/MessageDecoder.java 调试工具使用的是:卓岚TCP&UDP调试工具 1、在common\transport下面创建udp模块,仿照mqtt的创…

基于 HBase Phoenix 构建实时数仓(2)—— HBase 完全分布式安装

目录 一、开启 HDFS 机柜感知 1. 增加 core-site.xml 配置项 2. 创建机柜感知脚本 3. 创建机柜配置信息文件 4. 分发相关文件到其它节点 5. 重启 HDFS 使机柜感知生效 二、主机规划 三、安装配置 HBase 完全分布式集群 1. 在所有节点上配置环境变量 2. 解压、配置环境…

海外互联网专线主要解决企业哪些办公问题?

海外互联网专线 是一种专门为跨境企业提供的网络连接服务&#xff0c;旨在解决企业在海外办公过程中遇到的各种网络问题。海外互联网专线如何成为解决企业办公难题的利器&#xff0c;为企业提供稳定、高速的网络连接? 1、跨国远程办公&#xff1a; 随着全球化进程的加速&…

MyBatis Oracle 批量插入数据

MyBatis Oracle 批量插入数据 1.需求描述2.实现方案2.1 循环 insert 插入2.2 insert all 插入2.3 insert union all 插入 3.分析总结 系统&#xff1a;Win10 JDK&#xff1a;1.8.0_351 IDEA&#xff1a;2022.3.3 1.需求描述 在一次项目中实施过程中&#xff0c;后台需要将地区…

垃圾收集器底层算法

垃圾收集器底层算法 三色标记 在并发标记的过程中&#xff0c;因为标记期间应用线程还在继续跑&#xff0c;对象间的引用可能发生变化&#xff0c;多标和漏标的情况就有可能发生&#xff0c;这里我们引入“三色标记”来给大家解释下把Gcroots可达性分析遍历对象过程中遇到对象…