4.23刷题记录(栈与队列专题)
第一部分:基础知识
- 栈先进后出,队列先进先出
- 栈用stack实现,主要函数有pop,push,top
- 队列由queue或者deque实现,主要函数有front,back,push,pop,emplace(在队尾直接加一个元素)
第二部分:习题部分
(1)232. 用栈实现队列 - 力扣(LeetCode)
本题比较简单,只需要通过两个栈相互替换数据即可。
其中感觉比较巧妙的就是判断second是否为空,从而判断是否需要倒置。
class MyQueue {
public:stack<int>first;stack<int>second;MyQueue() {}void push(int x) {first.push(x);return;}int pop() {//注意此处弹出的是压在栈底的东西int x;if(second.empty()){while(!first.empty()){x=first.top();first.pop();second.push(x);}}x=second.top();second.pop();return x;}int peek() {int x;if(second.empty()){while(!first.empty()){x=first.top();first.pop();second.push(x);}}x=second.top();return x;}bool empty() {return first.empty()&&second.empty();}
};
(2)225. 用队列实现栈 - 力扣(LeetCode)
解题思路:此题目比较简单,仅需要对pop操作时候注意简化,将第一个队列中的全部元素拷贝到第二个队列中,并且将第一个剩余的弹出并保存返回,然后swap即可得到所需要的新的first
class MyStack {
public:queue<int>first;queue<int>second;MyStack() {}void push(int x) {first.push(x);}int pop() {//首先这里要进行判断的while(!first.empty()&&first.size()>1){second.push(first.front());first.pop();}int k=first.front();first.pop();swap(first,second);return k;}int top() {int x=this->pop();first.push(x);return x;}bool empty() {return first.empty()&&second.empty();}
};
(3)20. 有效的括号 - 力扣(LeetCode)
解题思路:本题目比较简单,需要考虑几种特殊情况
- 如果括号的数量是奇数,那么肯定不可能匹配成功
- 如果括号栈中最后还剩余,肯定不可能返回true
- 如果一左一右括号匹配不上,则直接返回flase
class Solution {
public:bool isValid(string s) {int n=s.size();if(n==0||n%2==1)return false;stack<char>stack;for(int i=0;i<s.size();i++){if(s[i]=='(')stack.push(')');else if(s[i]=='[')stack.push(']');else if(s[i]=='{')stack.push('}');else{if(stack.empty()||s[i]!=stack.top()){return false;}stack.pop();}}return stack.empty()==1;}
};
(4)1047. 删除字符串中的所有相邻重复项 - 力扣(LeetCode)
本题思路:如果遇到两个一样的则弹出,最后将栈中的元素进行翻转
class Solution {
public:string removeDuplicates(string s) {stack<char>stack;for(int i=0;i<s.size();i++){if(stack.empty()||s[i]!=stack.top()){stack.push(s[i]);continue;}else{stack.pop();}}string ans;while(!stack.empty()){ans+=stack.top();stack.pop();}reverse(ans.begin(),ans.end());return ans;}
};
(5)150. 逆波兰表达式求值 - 力扣(LeetCode)
真题思路比较简单,可以直接秒掉
class Solution {
public:int evalRPN(vector<string>& tokens) {stack<long long>operate;int n=tokens.size();for(int i=0;i<n;i++){//如果不是操作符则直接入栈if(tokens[i] != "+" && tokens[i] != "-" && tokens[i] != "*" && tokens[i] != "/"){operate.push(stoll(tokens[i]));}//如果是操作符则弹出运算else{long long num1=operate.top();operate.pop();long long num2=operate.top();operate.pop();if (tokens[i] == "+") operate.push(num2 + num1);if (tokens[i] == "-") operate.push(num2 - num1);if (tokens[i] == "*") operate.push(num2 * num1);if (tokens[i] == "/") operate.push(num2 / num1);}}return operate.top();}
};
(6)239. 滑动窗口最大值 - 力扣(LeetCode)
解题思路:用到了单调队列
- 注意两点:首先这个单调队列如何维护:不断存放更小值,如果遇到更大的值的话队首会被弹出。
- 检测队首的是否在这个区间内,用一个if就可以
- 最后必须i>=k-1的时候才允许加入,否则会出现第一二个元素,他不是范围内的最大值,但是他也加进去了。
class Solution {
public:vector<int> maxSlidingWindow(vector<int>& nums, int k) {//1,初始化vector<int>ans;deque<int>deq;//2.维护单调队列for(int i=0;i<nums.size();i++){//首先弹出超出范围的数值if(!deq.empty()&&deq.front()==i-k){deq.pop_front();}//维护单调队列while(!deq.empty()&&nums[i]>nums[deq.back()]){deq.pop_back();}//构造窗口deq.push_back(i);//加入结果if(i>=k-1){ans.push_back(nums[deq.front()]);}}return ans;}
};
(7)347. 前 K 个高频元素 - 力扣(LeetCode)
解题思路:堆
- 堆的三个元素分别为:存储变量,底层实现容器,比较逻辑。第一个比较简单,第二个直接在前面加vector<>即可,第三个比较逻辑可以通过static bool cmp设置一个函数,然后通过decltype(&cmp)来更改比较逻辑。也可以通过构造一个struct重载运算符。
- 构造完最大堆后,只需要不断弹出顶部元素即可。
class Solution {
public://第二种构造方法的structstruct ComparePerson {bool operator()(const pair<int,int>& a, const pair<int,int>& b) {return a.second < b.second; // 最大堆(如果比较函数返回 true,则表示第一个参数(a)应该排在第二个参数(b)的前面。//如果比较函数返回 false,则表示第一个参数(a)应该排在第二个参数(b)的后面。//这里面其实想放的是b的频率更大,所以应该返回true,所以a就放在了b的前面,//然后优先队列优先构造底部,所以a频率小的就在底部,顶部就是最大值。}};// 自定义比较函数,用于优先队列static bool cmp(const pair<int, int>& a, const pair<int, int>& b) {return a.second < b.second; // 用于最大堆}vector<int> topKFrequent(vector<int>& nums, int k) {unordered_map<int, int> cnt; // 用于统计每个数字的频率vector<int> ans; // 存储结果// 统计每个数字的频率for (int num : nums) {cnt[num]++;}// 构造最大堆priority_queue<pair<int, int>, vector<pair<int, int>>, decltype(&cmp)> maxHeap(cmp);//第二种构造方法//priority_queue<pair<int, int>, vector<pair<int, int>>, ComparePerson> maxHeap;//插入元素for(auto item:cnt){maxHeap.push(item);}//取出元素while(k>0&&!maxHeap.empty()){auto item=maxHeap.top();ans.push_back(item.first);maxHeap.pop();k--;}return ans;}
};