总结

基础补牢:【https://blog.csdn.net/tham_/article/details/44733101】

根据【http://c.biancheng.net/view/3354.html】,在栈讲义里看到了,链表插入头结点真的是在dummyhead和第一个之间插入的;在队列讲义里看到了双指针…

栈和队列都是【容器适配器】,可以出一道面试题:栈里面的元素在内存中是连续分布的么?
这个问题有两个陷阱:
陷阱1:栈是容器适配器,底层容器使用不同的容器,导致栈内数据在内存中是不是连续分布不确定。
陷阱2:缺省情况下,默认底层容器是deque,那么deque的在内存中的数据分布是什么样的呢? 答案是:不连续的,下文也会提到deque。

递归的实现是栈:每一次递归调用都会把函数的局部变量、参数值和返回地址等压入调用栈中
两种特殊的队列:滑动窗口最大值问题:单调队列 + 求前 K 个高频元素:优先级队列

  1. C++中stack 和 queue 是容器么?
    container adapter(容器适配器)
    栈是以底层容器完成其所有的工作,对外提供统一的接口,底层容器是可插拔的(也就是说我们可以控制使用哪种容器来实现栈的功能)。
    栈和队列的底层实现可以是vector,deque,list 都是可以的,时间复杂度是O( 1 )。

  2. 我们使用的stack 和 queue 是属于哪个版本的STL?
    SGI STL

  3. 我们使用的STL中stack 和 queue 是如何实现的?
    默认是以deque实现的

  4. stack 提供迭代器来遍历stack 和 queue 空间么?

232.用栈实现队列

必须用两个栈才能实现队列;
画图表示【很有必要】!

 /** 构造函数,必须有吗?(我知道这个题里有用到但是平时呢) */
//啥也没有,分分号都没有
//while最后记得推进循环进程,多次犯程序空转的错误
//this就是主函数里构造并使用的那个MyQueue吧?
class MyQueue {public:MyQueue() {// shuru;// shuchu;}void push(int x) {shuru.push(x);}int pop() {if(shuchu.empty()){while( !shuru.empty()){shuchu.push(shuru.top());shuru.pop();}}int res = shuchu.top();shuchu.pop();return res;}int peek() {int res = this->pop();//这就是没有参数的时候用this嘛shuchu.push(res);return res;}bool empty() {return(shuru.empty() && shuchu.empty());}
// private:放到公共变量里(并且在最前面),然后构造函数为空(why?因为题目要求的构造函数不需要变量?)stack<int> shuru;stack<int> shuchu;
};/*** Your MyQueue object will be instantiated and called as such:* MyQueue* obj = new MyQueue();* obj->push(x);* int param_2 = obj->pop();* int param_3 = obj->peek();* bool param_4 = obj->empty();使用栈来模式队列的行为,如果仅仅用一个栈,是一定不行的,所以需要两个栈一个输入栈,一个输出栈,这里要注意输入栈和输出栈的关系。*/

队列输入先后:4-3-2-1
back ············· ->························· front
——————————————————
-> 1 ············ 2 ············ 3············ 4·····->
——————————————————
push ············································ pop

225. 用队列实现栈

queue的常见用法:pop(), push( xxx ), front(), back(), empty();
stack的常见用法:pop(), push( xxx ), top(), empty();
来源[http://c.biancheng.net/view/479.html]

class MyStack {public:queue<int> st;MyStack() {}void push(int x) {st.push(x);}int pop() {///重点是这个函数,要把队列的最后一个元素删掉而不是简单的获取,所以只用back不够for(int i = 0; i< st.size()-1; i++){st.push(st.front());st.pop();}int res = st.front();st.pop();return res;}int top() {return st.back();}bool empty() {return (st.empty());}
};/*** 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();队列模拟栈,其实一个队列就够了,那么我们先说一说两个队列来实现栈的思路。
队列是先进先出的规则,把一个队列中的数据导入另一个队列中,数据的顺序并没有变,并没有变成先进后出的顺序。
所以用栈实现队列, 和用队列实现栈的思路还是不一样的,这取决于这两个数据结构的性质。
但是依然还是要用两个队列来模拟栈,只不过没有输入和输出的关系,而是另一个队列完全用又来备份的!
一个队列在模拟栈弹出元素的时候,只要将队列头部的元素(除了最后一个元素外) 重新添加到队列尾部,此时在去弹出元素就是栈的顺序了。*/

20.有效的括号

括号匹配是使用栈解决的经典问题。
后遇到的左括号要先闭合.

【代随】用了纯纯的栈,【力扣】用的栈+哈希表,~~分别默写了一下自己随便改改答案导致爆炸的情况可太多次了orz~

//【1】【代随】解法:栈
//一些技巧,在匹配左括号的时候,右括号先入栈,就只需要比较当前元素和栈顶相不相等就可以了,比左括号先入栈代码实现要简单的多了!
class Solution {public:bool isValid(string s) {stack<int> st;for (int i = 0; i < s.size(); i++) {if (s[i] == '(') st.push(')');else if (s[i] == '{') st.push('}');else if (s[i] == '[') st.push(']');// 第三种情况:遍历字符串匹配的过程中,栈已经为空了,没有匹配的字符了,说明右括号没有找到对应的左括号 return false// 第二种情况:遍历字符串匹配的过程中,发现栈里没有我们要匹配的字符。所以return falseelse if (st.empty() || st.top() != s[i]) return false;else st.pop(); // st.top() 与 s[i]相等,栈弹出元素}// 第一种情况:此时我们已经遍历完了字符串,但是栈不为空,说明有相应的左括号没有右括号来匹配,所以return false,否则就return truereturn st.empty();}
};
// // //【2】来源:力扣(LeetCode)
/*为了快速判断括号的类型,我们可以使用哈希表存储每一种括号。哈希表的键为右括号,值为相同类型的左括号。*/
class Solution{public:
bool isValid(string  s){// int n = s.size();unordered_map<char, char> pairs = {{')', '('},{']', '['}, {'}', '{'}};stack<char> stk;if (! s.size()%2 )return false;for (int i = 0; i <s.size(); i++){if (pairs.count(s[i])){if (stk.empty() || stk.top() != pairs[s[i]]) return false;//stk.empty() ||必须加!!不加有可能移除(空了就没有top了)else stk.pop();}else stk.push(s[i]);}return stk.empty();
}
};
//【3】自己写的
//char是字符类型, String是字符串类型;String内部用来存储的结果是一个char字符数组。
//stack<int> st 也可以....
//if语句执行行只有1行的话可以不加{},直接跟在if()后面;
class Solution {public:bool isValid(string s) {stack<char> st;for(int i = 0;i <s.size(); i++ ){if(s[i]=='[' || s[i]=='{' || s[i]=='(') st.push(s[i]);else{if(st.empty()) return false;else if((s[i]==']' && st.top()=='[') || (s[i]=='}' && st.top()=='{') || (s[i]==')' && st.top()=='(') ) st.pop();else return false;}}if(!st.empty()) return false;return true;}
};
//由于栈结构的特殊性,非常适合做对称匹配类的题目。
//要写代码之前要分析好有哪几种不匹配的情况,这里有三种不匹配的情况:左多了、右多了、不多不少但不成对(类型不匹配)

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

匹配问题都是栈的强项
拿字符串直接作为栈,(用字符串模拟栈)这样省去了栈还要转为字符串的操作,但是相应函数就是vector< char >对应的pop_back 和push_back

class Solution {public:string removeDuplicates(string s) {stack<char> st;st.push(s[0]);if(s.size()==1) return s;for(int i = 1; i<s.size(); i++){if(!st.empty() && s[i]==st.top()) {st.pop();continue;}else st.push(s[i]);}string res;while(!st.empty()){res+=st.top();st.pop();}reverse(res.begin(), res.end());return res;}
};

150. 逆波兰表达式求值

在上一题1047.删除字符串中的所有相邻重复项 提到了 递归就是用栈来实现的。

stoi()函数——将数字字符转化位int输出;使用之前要包含头文件#include< string >

347.前 K 个高频元素

!还没搞懂的知识点:
小顶堆
class中class
bool operator()()
priority_queue< 123 >
unordered_map<int, int>:: iterator it

思路
这道题目主要涉及到如下三块内容:
要统计元素出现频率
对频率排序
找出前K个高频元素

首先统计元素出现的频率,这一类的问题可以使用map来进行统计。
然后是对频率进行排序,这里我们可以使用一种 容器适配器就是优先级队列

(1)什么是优先级队列呢?

其实就是一个披着队列外衣的,因为优先级队列对外接口只是从队头取元素,从队尾添加元素,再无其他取元素的方式,看起来就是一个队列。
而且优先级队列内部元素是自动依照元素的权值排列
缺省情况下priority_queue利用max-heap(大顶堆)完成对元素的排序,这个大顶堆是以vector为表现形式的complete binary tree(完全二叉树)。

(2)什么是呢?

堆是一棵完全二叉树,树中每个结点的值都不小于(或不大于)其左右孩子的值。可以把堆分为大顶堆和小顶堆。 如果父亲结点是大于等于左右孩子就是大顶堆,小于等于左右孩子就是小顶堆。
所以大家经常说的大顶堆(堆头是最大元素****)小顶堆(堆头是最小元素),如果懒得自己实现的话,就**直接用priority_queue(优先级队列)**就可以实现了,底层实现都是一样的,从小到大排就是小顶堆,从大到小排就是大顶堆。
堆的这种特性非常的有用,堆常常被当做优先队列使用,因为可以快速的访问到“最重要”的元素。

注意:从栈顶top()处pop

(3)本题我们就要使用优先级队列来对部分频率进行排序。

为什么不用快排呢, 使用快排要将map转换为vector的结构,然后对整个数组进行排序, 而这种场景下,我们其实只需要维护k个有序的序列就可以了,所以使用优先级队列是最优的。
此时要思考一下,是使用小顶堆呢,还是大顶堆?有的同学一想,题目要求前 K 个高频元素,那么果断用大顶堆啊。那么问题来了,定义一个大小为k的大顶堆,在每次移动更新大顶堆的时候,每次弹出都把最大的元素弹出去了,那么怎么保留下来前K个高频元素呢。而且使用大顶堆就要把所有元素都进行排序,那能不能只排序k个元素呢?
所以我们要用小顶堆,因为要统计最大前k个元素,只有小顶堆每次将最小的元素(从队头)弹出,最后小顶堆里积累的才是前k个最大元素

// 链接:https://leetcode.cn/problems/top-k-frequent-elements/solution/c-xiao-bai-you-hao-you-xian-dui-lie-de-j-53ay/
// 无标注版,注意一些pair的使用、priority_queue的使用及其排序结构体的定义
class Solution{public:vector<int> topKFrequent(vector<int>& nums, int k){unordered_map<int,int> map;for(int i = 0; i< nums.size(); i++) map[nums[i]]++;///默认每个key的val初始是0所以可以直接++   struct myComparison{bool operator()(pair<int, int>& p1, pair<int, int>& p2) { return p1.second > p2.second; }// /函数有(),class和struct无()!!!operator() !!!NO second()!!!};   priority_queue <pair<int,int>, vector<pair<int,int>>, myComparison> q;  ///NO myconmarison()for(auto& a:map){q.push(a);if(q.size()>k) q.pop();}vector<int> res;while(!q.empty()){res.push_back(q.top().first);q.pop();}reverse (res.begin(), res.end());return res;}};
class Solution {public:vector<int> topKFrequent(vector<int>& nums, int k) {//1.map记录元素出现的次数unordered_map<int,int>map;//两个int分别是元素和出现的次数for(auto& c:nums){map[c]++;}//2.利用优先队列,将出现次数排序//自定义优先队列的比较方式,小顶堆;注意其形式不是在小class里就是在小struct里,都是无()有{};  struct myComparison{bool operator()(pair<int,int>&p1,pair<int,int>&p2){return p1.second>p2.second;//小顶堆是大于号}};//创建优先队列priority_queue<pair<int,int>,vector<pair<int,int>>,myComparison> q;//遍历map中的元素//1.管他是啥,先入队列,队列会自己排序将他放在合适的位置//2.若队列元素个数超过k,则将栈顶元素出栈(栈顶元素一定是最小的那个)//并且从栈顶top()处pop,使得最小的被弹出for(auto& a:map){q.push(a);if(q.size()>k){q.pop(); }}//将结果导出,注意要翻转vector<int>res;while(!q.empty()){res.push_back(q.top().first);//emplaceq.pop();}reverse(res.begin(), res.end());return res;}
};

【代码随想录】【LeetCode】自学笔记07 - 栈和队列相关推荐

  1. JAVA自学笔记07

    JAVA自学笔记07 1.构造方法 1) 例如:Student s = new Student();//构造方法 System.out.println(s);// Student@e5bbd6 2)功 ...

  2. 计算机二级循环队列知识点,考点!计算机二级考试公共基础知识冲刺复习笔记:栈、队列和循环队列...

    小编所收集到的相关计算机二级考试公共基础知识冲刺复习笔记:栈.队列和循环队列的资料 大家要认真阅读哦! 1.栈(Stack)又称堆栈. (1)栈是一种运算受限的线性表,其限制是仅允许在表的一端进行插入 ...

  3. 数据结构~07.栈和队列的基本概念

    数据结构~07.栈和队列的基本概念 本文是上一篇文章的后续,详情点击该链接~ 栈的定义: 栈是一种只能在一端进行插入或删除的线性表.其中,允许插入或删除的一端为栈顶(TOP).栈顶由一个称为栈顶指针的 ...

  4. Leetcode刷题笔记:栈与队列篇

    基础知识 栈和队列的原理大家应该很熟悉了,队列是先进先出,栈是先进后出. 如图所示: 那么我这里再列出四个关于栈的问题,大家可以思考一下.以下是以C++为例,使用其他编程语言的同学也对应思考一下,自己 ...

  5. 代码随想录算法训练营第07天 | 454.四数相加II 、383. 赎金信、315. 三数之和 、18. 四数之和

    题目 题目链接,代码 题目链接,代码 题目链接,代码 题目链接,代码 初见思路 454.四数相加II 直接看了解析,想通的话还是比较好理解的.用一个map来记录两个数组的和以及出现次数, key为i+ ...

  6. 【Leetcode】232.用栈实现队列

    题目链接:232.用栈实现队列 关键字:栈.队列 解题思路 使用两个栈实现队列,其中一个栈正常使用,另一个栈用来保存逆序数据 代码实现 class MyQueue { public:/** Initi ...

  7. c语言中缀表达式求值_数据结构考研笔记之栈与队列(四)栈与队列应用括号匹配、中缀表达式转前缀后缀问题...

    文字:独木 排版:独木 图片:独木 栈与队列 1.括号匹配问题 栈 例题1 例题2-----不匹配例题1 例题3-----不匹配例题2 2. 表达式求值问题 例题 1.中缀表达式转前缀表达式 2.中缀 ...

  8. 【LeetCode刷题】栈与队列专题

    前言:之前对栈与队列一直停留在表层概念的理解上,不知道怎么用,借刷题的机会来深入理解一下. 文章目录 20 有效括号 1047. 删除字符串中的所有相邻重复项 栈版本 双指针版本 150. 逆波兰表达 ...

  9. Leetcode(1)——数组、栈、队列

    格式: 题号+题名+简单思路+code T1: 两数之和 不考虑去重,只找出第一个解:使用哈希表记录出现过的数字,O(N)时间复杂度 func twoSum(nums []int, target in ...

最新文章

  1. 2018/8/26 PSO-based Clustering Techniques to Solve Multimodal Optimization Problems: A Survey
  2. 3Blue1Brown深度学习笔记 深度学习之神经网络的结构 Part 1 ver 2.0
  3. SqlServer 中的临时表与表变量
  4. vscode设置代码编辑时组合键代替方向键移动光标
  5. 如何重置云服务器系统
  6. 8086键盘输入实验——《x86汇编语言:从实模式到保护模式》读书笔记07
  7. 02_混淆矩阵、准确率(Accuracy)、精确率(Precision)、召回率(Recall)、F值(F-Measure) +Roc曲线和PR曲线+sklearn中分类模型评估API+ 自己补充整理
  8. WKWebView进度及title
  9. LeetCode 593. 有效的正方形(数学)
  10. 企业需要的C++程序员
  11. 他走了,留下了3800亿元的帝国
  12. 瑞星正版序列号,得来全不费功夫!Google搜索技巧
  13. jsp js弹出网页对话框
  14. EWSA1.50.0.298栈溢出错误
  15. base家族:base16、base32和base64,转码原理
  16. 在nginx中编写html,码头不会在nginx html根目录中创建文件夹
  17. “棱镜”入侵手机App, 爱加密有效防窃听
  18. 开源表单推荐:Tduck 填鸭 —— 表单收集器
  19. [Unity Mirror] 自定义角色生成
  20. mysql数据库导出数据乱码问题_Mysql数据库导出来的是乱码如何解决

热门文章

  1. 验证sqlserver 2000 sp4补丁是否安装成功(安装补丁后可以远程访问)
  2. 扩展lucas学习笔记
  3. php环境下,两种汇率接口,已经测试通过
  4. 单射、满射和双射(一 一映射)
  5. contiki 操作教程
  6. 总有人问我:独立站该怎么玩?3个案例,你看完就懂了
  7. 在超算上用sentieon快速完成NGS的变异检测
  8. 【5G系列】一文打尽 IMSI、TMSI、GUTI、P-TMSI、S-TMSI、LMSI、5G-TMSI、5G-GUTI、5G-S-TMSI
  9. oracle fnd global,Oracle EBS fnd_request.submit_request 与 Fnd_concurrent.wait_for_ruqest
  10. 江恩 计算机,江恩理论基础篇