【代码随想录算法训练营——Day11】栈与队列——150.逆波兰表达式求值、239.滑动窗口最大值、347.前K个高频元素
LeetCode题目链接
https://leetcode.cn/problems/evaluate-reverse-polish-notation/
https://leetcode.cn/problems/sliding-window-maximum/
https://leetcode.cn/problems/top-k-frequent-elements/
题解
150.逆波兰表达式求值、
不能用tokens[i] >= "0" && tokens[i] <= "9"
来判断数字,因为会有三位数。被AI发现的bug。
239.滑动窗口最大值
拿到题目,经提示已经知道是用队列。但是重要的是用队列记录什么。
看题解(视频),维护一个单调队列,由我们自己来实现,每次新加入一个元素到队列里时,把前面所有小于其值的值都pop出队列,维持队列出口为当前窗口的最大值。
实现代码的过程中,有一个不明白的点是,为什么当前维护的最大值不会是已经在窗口左侧边缘外的值?找到原因了,代码写的不是很对,要弹出窗口前面的那个值。
又改了两个地方,一个是改成deque的实现,一个是新加入的值要与back()比较,如果比较的值更小要pop_back(),从尾部弹出,可以防止[3,1,2]以及其下一步的[1,2,0]这样的队列维护值发生。
347.前K个高频元素
想了用hash来存,但排序会丢失下标的信息;再想到用map来存,但不好根据值排序。
看题解,发现用map排序行。于是写了个下一回写不出的代码,主要是sort的cmp集成代码,还有遍历pair代码也写不出。感觉都是语法问题,写几次就会了。
接着看题解,语法也挺难,思路,要用到小顶堆,堆的数据结构和代码没怎么写过,下回再补。
代码
//150.逆波兰表达式求值
#include <iostream>
#include <vector>
#include <string>
#include <stack>
using namespace std;class Solution {
public:int evalRPN(vector<string>& tokens) {stack<int> st;for (int i = 0;i < tokens.size();i++) {if(tokens[i] == "+" || tokens[i] == "-" || tokens[i] == "*" || tokens[i] == "/") {int tmp1 = st.top();st.pop();int tmp2 = st.top();st.pop();if (tokens[i] == "+") st.push(tmp1 + tmp2);else if (tokens[i] == "-") st.push(tmp2 - tmp1);else if (tokens[i] == "*") st.push(tmp1 * tmp2);else st.push(tmp2 / tmp1);}else {st.push(stoi(tokens[i]));}}return st.top();}
};int main() {vector<string> tokens = { "10","6","9","3","+","-11","*","/","*","17","+","5","+" };Solution s;printf("%d", s.evalRPN(tokens));return 0;
}
//239.滑动窗口最大值
#include <iostream>
#include <vector>
#include <queue>
using namespace std;class Solution {
public:vector<int> maxSlidingWindow(vector<int>& nums, int k) {vector<int> result;//queue<int> que;deque<int> que;for (int i = 0;i < k;i++) {/*while (!que.empty() && que.front() < nums[i]) {que.pop_front();}*/while (!que.empty() && nums[i] > que.back()) {que.pop_back();}que.push_back(nums[i]);}result.push_back(que.front());for (int i = k;i < nums.size();i++) {if (!que.empty() && nums[i - k] == que.front()) {que.pop_front();}/*while (!que.empty() && que.front() < nums[i]) {que.pop();}*/while (!que.empty() && nums[i] > que.back()) {que.pop_back();}que.push_back(nums[i]);result.push_back(que.front());}return result;}
};int main() {vector<int> nums = { 1,3,1,2,0,5 };int k = 3;Solution s;vector<int> result = s.maxSlidingWindow(nums, k);for (int i = 0;i < result.size();i++) {printf("%d ", result[i]);}return 0;
}
//347.前K个高频元素
vector<int> topKFrequent(vector<int>& nums, int k) {map<int, int> hash;for(int i = 0;i < nums.size();i++){hash[nums[i]]++;}vector<pair<int, int>> tmp(hash.begin(), hash.end());sort(tmp.begin(), tmp.end(), [](const pair<int, int>& a, const pair<int, int>& b) {return a.second > b.second; // 按照值降序排列});vector<int> result;int num = 0;for(const auto& pair : tmp){if(num < k){result.push_back(pair.first);num++;}}return result;}