stack、queue 和 priority_queue 相关的练习

news2024/11/19 5:34:39

目录

一、stack 相关的练习

1.1 - 最小栈

1.2 - 栈的压入、弹出序列

1.3 - 逆波兰表达式求值

1.4 - 用栈实现队列

二、queue 相关的练习

2.1 - 二叉树的层序遍历

2.2 - 二叉树的层序遍历 II

2.3 - 用队列实现栈

三、priority_queue 相关的练习

3.1 - 数组中的第K个最大元素


 


一、stack 相关的练习

1.1 - 最小栈

class MinStack {
public:
    void push(int val) {
        st.push(val);
        if (min_st.empty() || val <= min_st.top())
            min_st.push(val);
    }
    
    void pop() {
        if (st.top() == min_st.top())
            min_st.pop();
        st.pop();
    }
    
    int top() {
        return st.top();
    }
    
    int getMin() {
        return min_st.top();
    }
private:
    stack<int> st;
    stack<int> min_st;
};

思路

 

1.2 - 栈的压入、弹出序列

class Solution {
public:
    bool IsPopOrder(vector<int>& pushV, vector<int>& popV) {
        if (pushV.size() != popV.size())
            return false;
​
        stack<int> st;
        int i = 0;
        int j = 0;
        while (i < pushV.size())
        {
            if (pushV[i] != popV[j])
            {
                st.push(pushV[i++]);
            }
            else
            {
                ++i;  // 入栈
                ++j;  // 出栈
​
                while (!st.empty() && popV[j] == st.top())
                {
                    st.pop();
                    ++j;
                }
            }
        }
        return st.empty();
    }
};

思路

根据入栈和出栈序列,用一个栈 st 来模拟整个过程。

  1. 如果入栈序列中待入栈的数字,即 pushV[i],不等于出栈序列中待出栈的数字,即 popV[j],则将 pushV[i] 入栈。

  2. 反之,则表示数字入栈后马上就要出栈,然后还要判断后面待出栈的数字是否等于栈顶元素,即判断是否还有数字需要出栈。

1.3 - 逆波兰表达式求值

class Solution {
public:
    int evalRPN(vector<string>& tokens) {
        stack<int> st;
        for (auto& s : tokens)
        {
            if (s == "+" || s == "-" || s == "*" || s == "/")
            {
                int right = st.top();  // 右操作数
                st.pop();
                int left = st.top();  // 左操作数
                st.pop();
​
                switch(s[0])
                {
                    case '+':
                        st.push(left + right);
                        break;
                    case '-':
                        st.push(left - right);
                        break;
                    case '*':
                        st.push(left * right);
                        break;
                    case '/':
                        st.push(left / right);
                        break;
                }
            }
            else
            {
                st.push(stoi(s));
            }
        }
        return st.top();
    }
};

思路

  1. 遇到操作数,则将其入栈。

  2. 遇到操作符,则取出栈顶两个数字分别作为右操作数和左操作数进行运算,然后再将运算结果压入栈中。

注意:在判断字符串 s 是否为操作符时,不能使用 s[0] == '+' || s[0] == '-' || s[0] == '*' || s[0] == '/' 进行判断,因为当 s 表示负数时,例如 "-11",s[0] 也是 '-'

而在已经确定字符串 s 为操作符时,就可以使用 s[0] 对操作符进行区分了

1.4 - 用栈实现队列

class MyQueue {
public:
    void push(int x) {
        in_st.push(x);
    }
    
    int peek() {
        if (out_st.empty())
        {
            while (!in_st.empty())
            {
                out_st.push(in_st.top());
                in_st.pop();
            }
        }
        return out_st.top();
    }
​
    int pop() {
        int front = peek();
        out_st.pop();
        return front;
    }
    
    bool empty() {
        return in_st.empty() && out_st.empty();
    }
private:
    stack<int> in_st;  // 用于入队的栈
    stack<int> out_st;  // 用于出队的栈
};


二、queue 相关的练习

2.1 - 二叉树的层序遍历

题目描述

给你二叉树的根节点 root,返回其节点值的 层序遍历(即逐层地、从左到右访问所有节点)。

代码实现

class Solution {
public:
    vector<vector<int>> levelOrder(TreeNode* root) {
        queue<TreeNode*> q;
        size_t levelSize = 0;  // 所在层数的节点个数
        if (root)
        {
            q.push(root);
            levelSize = 1;
        }
        
        vector<vector<int>> vv;
        while (!q.empty())
        {
            vector<int> v;
            for (size_t i = 0; i < levelSize; ++i)
            {
                TreeNode* front = q.front();
                q.pop();
                v.push_back(front->val);
                if (front->left)
                    q.push(front->left);
                if (front->right)
                    q.push(front->right);
            }
            vv.push_back(v);
            levelSize = q.size();
        }
        return vv;
    }
};

2.2 - 二叉树的层序遍历 II

题目描述

给你二叉树的根节点 root,返回其节点值 自底向上的层序遍历(即按从叶子节点所在层到根节点所在的层,逐层从左向右遍历)。

代码实现

class Solution {
public:
    vector<vector<int>> levelOrderBottom(TreeNode* root) {
        queue<TreeNode*> q;
        size_t levelSize = 0;  // 所在层数的节点个数
        if (root)
        {
            q.push(root);
            levelSize = 1;
        }
        
        vector<vector<int>> vv;
        while (!q.empty())
        {
            vector<int> v;
            for (size_t i = 0; i < levelSize; ++i)
            {
                TreeNode* front = q.front();
                q.pop();
                v.push_back(front->val);
                if (front->left)
                    q.push(front->left);
                if (front->right)
                    q.push(front->right);
            }
            vv.push_back(v);
            levelSize = q.size();
        }
        reverse(vv.begin(), vv.end());  // 逆置
        return vv;
    }
};

2.3 - 用队列实现栈

class MyStack {
public:
    void push(int x) {
        // 让一个队列存储数据,让另一个队列为空
        if (!q1.empty())
            q1.push(x);
        else
            q2.push(x);
    }
    
    int pop() {
        // 前提是栈非空
        assert(!empty());
        // 找到非空队列和空队列
        queue<int>* empty = &q1;
        queue<int>* nonempty = &q2;
        if (!q1.empty())
        {
            empty = &q2;
            nonempty = &q1;
        }
        // 将非空队列中的数据移至空队列中,仅仅保留最后一个数据
        while (nonempty->size() > 1)
        {
            empty->push(nonempty->front());
            nonempty->pop();
        }
        int top = nonempty->front();
        nonempty->pop();
        return top;
    }
    
    int top() {
        assert(!empty());
        if (!q1.empty())
            return q1.back();
        else
            return q2.back();
    }
​
    bool empty() {
        return q1.empty() && q2.empty();
    }
private:
    queue<int> q1;
    queue<int> q2;
};


三、priority_queue 相关的练习

3.1 - 数组中的第K个最大元素

方法一

class Solution {
public:
    int findKthLargest(vector<int>& nums, int k) {
        // 排升序
        // sort(nums.begin(), nums.end());
        // return nums[nums.size() - k];
​
        // 排降序
        sort(nums.begin(), nums.end(), greater<int>());
        return nums[k - 1];
    }
};

无论是排升序,还是排降序,时间复杂度都是 O(n * logn)

方法二

class Solution {
public:
    int findKthLargest(vector<int>& nums, int k) {
        priority_queue<int> pq(nums.begin(), nums.end());
        while (--k)  // 注意:循环次数为 k - 1
        {
            pq.pop();
        }
        return pq.top();
    }
};

时间复杂度为 O(n + k * logn)

方法三

class Solution {
public:
    int findKthLargest(vector<int>& nums, int k) {
        priority_queue<int, vector<int>, greater<int>> pq(nums.begin(), nums.begin() + k);
        for (size_t i = k; i < nums.size(); ++i)
        {
            if (nums[i] > pq.top())
            {
                pq.pop();
                pq.push(nums[i]);
            }
        }
        return pq.top();
    }
};

时间复杂度为 O(k + (n - k) * logk)

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

微信小程序胶囊位置计算,避开胶囊位置

由于小程序在不同的手机上顶部布局会发生变化&#xff0c;不能正确避开胶囊位置&#xff0c;所以通过官方给出的胶囊信息&#xff0c;可以计算出胶囊位置&#xff0c;并避开 图示例&#xff1a; 此处思路是&#xff0c;获取胶囊底部位置&#xff0c;并拉开10个px 计算出来的…

计算机组成与设计 Patterson Hennessy 笔记(二)MIPS 指令集

计算机的语言&#xff1a;汇编指令集 也就是指令集。本书主要介绍 MIPS 指令集。 汇编指令 算数运算&#xff1a; add a,b,c # abc sub a,b,c # ab-cMIPS 汇编的注释是 # 号。 由于MIPS中寄存器大小32位&#xff0c;是基本访问单位&#xff0c;因此也被称为一个字 word。M…

React 生态应用 - React Router(2)

目录 RouteProps Route参数 重定向Redirect【v5】&& 【v6实现】 导航的处理 练习 使用随堂demo实现一个简单的鉴权&#xff1a;当前用户是admin的时候&#xff0c;可以访问所有菜单&#xff1b;当前用户是user的时候&#xff0c;无法访问admin页面&#xff08;用…

LVS负载均衡集群和NAT模式群集部署

目录 1、什么是集群 2、集群的使用场景 3、集群的分类 4、负载均衡器的集群架构 5、负载均衡器的集群的工作模式 6、 LVS虚拟服务器 7、LVS的负载均衡算法 8、LVS集群创建与管理 9、LVS的管理工具 10、实验&#xff1a; nat模式 LVS负载均衡群集部署 1、什么是集群 将…

使用 pyodbc 解析chrome浏览器导出的书签并保存到 Microsoft Access 数据库

使用 wxPython 和 pyodbc 解析书签并保存到 Microsoft Access 数据库的示例博客&#xff1a; 本篇博客介绍了如何使用 wxPython 和 pyodbc 库创建一个简单的应用程序&#xff0c;用于解析 HTML 文件中的书签并将其保存到 Microsoft Access 数据库中。通过这个示例&#xff0c;您…

手把手教你使用人工智能生成游戏 3D 素材

引言 生成式 AI 已成为游戏开发中艺术工作流的重要组成部分。然而&#xff0c;正如我在之前的文章: 《AI 制作 3D 素材&#xff5c;基于 AI 5 天创建一个农场游戏&#xff0c;第 3 天》中描述的&#xff0c;从文本到 3D 的实用性仍落后于 2D。不过&#xff0c;这种情况正在改变…

集成大淘客实现多个电商平台的数据互连

大淘客是一家导购优惠平台。 它通过整合多个电商平台的商品和优惠信息&#xff0c;为用户提供高品质、低价格的商品推荐和购物指南。 场景描述&#xff1a; 基于大淘客开放平台的API能力&#xff0c;零代码实现多个电商平台的导购数据、商品数据、账号销售数据和其它应用数据…

51单片机简易数字万用表(电阻电流电压测量)仿真设计( proteus仿真+程序+报告+讲解视频)

目录 51单片机简易数字万用表(电阻电流电压测量)仿真设计( proteus仿真程序报告讲解视频&#xff09;1.主要功能&#xff1a;2.仿真3. 程序代码4. 设计资料内容清单&下载地址 51单片机简易数字万用表(电阻电流电压测量)仿真设计( proteus仿真程序报告讲解视频&#xff09; …

KeilMDK V5编译器的安装

1、安装原因 目前keil官网最新版本的Keil都是默认安装V6编译器&#xff0c;不再自动安装V5编译器&#xff0c;而V5与V6编译器在编译的时候有很多代码不兼容&#xff0c;导致工程编译失败&#xff0c;所以我们使用新版keil5的时候&#xff0c;要用V5编译器就要自己安装V5编译器。…

微信小程序自定义tabBar详细教程,且自适应尺寸和实现高斯模糊版

IOS示例&#xff1a; 安卓示例&#xff1a; 高斯模糊示例&#xff1a; WXML代码&#xff1a; <view class"tabbar"><view style"{{selectindex&&index0?color: #ef3166;:}}"class"tabbar-item {{ select index ? tabbar-select …

WMS系统条码管理

一、条码的基本概念和应用&#xff1a; WMS系统条码管理是指在仓库管理系统中使用条码技术对货物、物料和库存信息进行标识、跟踪和管理的过程。它基于条码识别和数据采集技术&#xff0c;通过在物料或货物上粘贴或打印条码标签&#xff0c;并使用条码扫描设备进行扫描和读取&…

深入理解内存 —— 函数栈帧的创建与销毁

前言 一位优秀的程序员&#xff0c;必须对内存的分布有深刻的理解&#xff0c;在初学编程的时候&#xff0c;往往有诸如以下很多问题困扰着初学者&#xff0c;而通过今天的分享&#xff0c;我们就可以通过自己的观察&#xff0c;将这些问题统统解决掉 局部变量是怎么创建的&…

架构师必备--高可用高性能分布式数据库Tidb安装部署实践

本文针对分布式、高可用的tidb数据库&#xff0c;从搭建实际生产环境的集群服务&#xff0c;介绍下tidb的安装流程、安装前的环境检测和系统优化、服务访问等方面介绍下具体的流程&#xff0c;希望对大家熟悉和了解tidb数据库有所帮助&#xff0c;减少不必要的弯路。 1.概述 …

图形推理|解题思路汇总

一、图形推理题常见题型 &#xff08;一&#xff09;图形的位置 图形的位置主要是指与图形位置相关的图形推理考点规律。 这类题目的图形特点通常有以下两类: (1)题干图形相似程度很高&#xff0c;只是某些部分的位置有差异-&#xff0c;考虑移动、旋转与翻转。…

自动编码器中的马尔可夫链蒙特卡罗期望最大化 (MCMC-EM):使用贝叶斯推理增强学习

一、介绍 自动编码器 自动编码器是强大的无监督学习算法&#xff0c;用于表示学习和降维。它们的工作原理是将输入数据编码为低维表示形式&#xff0c;然后将其解码回以重建原始数据。训练自动编码器通常涉及优化参数以最小化重建误差。然而&#xff0c;传统的优化技术&#xf…

如何通过MAT排查生产环境服务内存溢出

前言 前段时间&#xff0c;运维反馈生产环境翻译服务某个节点触发内存告警了。运维在重启节点之前&#xff0c;生成了dump快照&#xff0c;这里介绍下如何使用MAT内存分析工具来排查服务内存高占用问题。 MAT简介 MAT是Memory Analyzer的简称&#xff0c;它是一款功能强大的…

前端技术Vue学习笔记--005

Vue学习笔记 一、非父子通信-event bus 事件总线 作用&#xff1a;非父子组件之间&#xff0c;进行简易消息传递。&#xff08;复杂场景用----Vuex&#xff09; 使用步骤&#xff1a; 创建一个都能访问的事件总线 &#xff08;空Vue实例&#xff09;-----utils/EventBus.js /…

浅谈更糟糕的 CS_CLASSDC 标志位的作用

在上一篇文章中&#xff0c;我们了解了 CS_OWNDC 标志位的历史&#xff0c;也说明了设计它的初衷。 这个标志位一开始看起来是个挺好的设计&#xff0c;但是如果你多琢磨一会儿&#xff0c;就会发现它不是一个好主意。今天我们来看看更糟的。 CS_CLASSDC 标志位有点类似 CS_OW…

shell脚本文本三剑客sed

shell脚本文本三剑客sed 一.Sed编辑器1.1sed概述1.2sed工作流程1.3sed基本法1.4sed常用选项1.5sed命令的常用操作 二.sed命令使用2.1打印内容2.2删除内容示例5&#xff1a;先备份内容在删除2.3插入内容2.4取反2.5搜索替代2.6分组调用 一.Sed编辑器 1.1sed概述 sed编辑器是一种…

Linux 虚拟机Ubuntu22.04版本通过远程连接连接不上,输入ifconfig只能看到127.0.0.1的解决办法

之前给虚拟机配置静态IP之后&#xff0c;可以直接通过主机Vscode远程连接。但是前一段时间把主机的TCP/IPV4静态IP设置了一下之后&#xff0c;再连接虚拟机就连不上了&#xff0c;于是参考解决虚拟机不能上网ifconfig只显示127.0.0.1的问题&#xff0c;又可以连接上了&#xff…