letcode 分类练习 栈和队列 150. 逆波兰表达式求值 239. 滑动窗口最大值 347.前 K 个高频元素
150. 逆波兰表达式求值
注意字符串转数值用stoll,stoll是C++标准库中的一个函数,全称为std::stoll,它的作用是将字符串(std::string类型)转换为带符号的长整型(long long int类型)
class Solution {
public:
int evalRPN(vector<string>& tokens) {
stack<long long> st;
for(auto s : tokens){
if(s == "+" || s == "-" || s == "*" || s == "/"){
long long num_2 = st.top();
st.pop();
long long num_1 = st.top();
st.pop();
if(s == "+") num_1 = num_1 + num_2;
if(s == "*") num_1 = num_1 * num_2;
if(s == "-") num_1 = num_1 - num_2;
if(s == "/") num_1 = num_1 / num_2;
st.push(num_1);
}else{
st.push(stoll(s));
}
}
return st.top();
}
};
239. 滑动窗口最大值
这道题,我们需要维护一个队列,并且我们可以每移动一次窗口,pop掉队头结点,push进队尾节点,并且还能输出队列中的max值,所以肯定得使用双端队列deque,然后为了每次都能输出队列的max值,所以我们需要采用单调队列结构:
class Solution {
public:
vector<int> maxSlidingWindow(vector<int>& nums, int k) {
deque<int> q;
int n = nums.size();
vector<int> result;
for(int i = 0;i< n; i++){
if(i>k-1 && q.front() == nums[i-k])q.pop_front();
// 这里不能小于等于,因为要确保最大值的唯一性
// 例如[3,3,3]我们要始终保证最大值在队头结点
while(!q.empty() && q.back() < nums[i] ){
q.pop_back();
}
q.push_back(nums[i]);
if(i>=k-1)result.push_back(q.front());
}
return result;
}
};
347. 前 K 个高频元素
统计频次,很自然就想到了用map来记录次数,现在关键是要对map的value做一个排序,并输出频次最大k个的key值。维护k个最大,这个可以采用k个节点的小顶堆。
class Solution {
public:
struct cmp{
bool operator()(pair<int, int>& a, pair<int, int>& b){
// 大顶堆对应less即<
// 小顶堆对应greater即>
return a.second>b.second;
}};
vector<int> topKFrequent(vector<int>& nums, int k) {
unordered_map<int,int> map;
for(int i = 0;i<nums.size();i++){
map[nums[i]] ++;
}
priority_queue<pair<int, int>, vector<pair<int, int>>, cmp>q;
for(auto kv : map){
q.push(pair(kv.first, kv.second));
if(q.size() > k)q.pop();
}
vector<int> result;
for(int i =0;i<k;i++){
int key = q.top().first;
q.pop();
result.push_back(key);
}
return result;
}
};