150. 逆波兰表达式求值
思想:逆波兰表达式实际上就是后缀表达式。。。整了一个高大上的名字 思路就是碰到数字压栈,碰到操作符出栈。栈顶的两个元素进行计算,然后把结果压回栈 就可以了。
遇到的问题:不知道怎么把字符串转变为int型,查找了解了stoi函数。
class Solution {
public:
int evalRPN(vector<string>& tokens) {
// 逆波兰表达式实际上就是后缀表达式。。。整了一个高大上的名字
// 思路就是碰到数字压栈,碰到操作符出栈栈顶的两个元素进行计算
// 然后把结果压回栈 就可以了
stack<int> ans;
for (int i = 0; i < tokens.size(); i++) {
if (tokens[i] == "+" || tokens[i] == "-" || tokens[i] == "*" ||tokens[i] == "/") {
int temp1 = ans.top(); // 栈顶的第一个元素
ans.pop();
int temp2 = ans.top();
ans.pop();
//这里要把握好两个值的先后顺序
if (tokens[i] == "+") ans.push(temp2 + temp1);
else if (tokens[i] == "-") ans.push(temp2 - temp1);
else if (tokens[i] == "*") ans.push(temp2 * temp1);
else ans.push(temp2 / temp1);
}
//在这里碰到了问题 忘记把string转成int了 在网上学习了stoi函数 可以实现该功能
else ans.push(stoi(tokens[i]));
}
return ans.top();
}
};
239. 滑动窗口最大值
思想:这里用到了单调队列(deque容器实现)。如果下一个push进去的元素大于之前的最大元素的话,则之前元素全部出队deq.pop_front()即可。但如果只是当前push的元素大于队尾元素时,则队尾元素出队deq.pop_back()。需要区别这两种pop。之后滑动窗口移动,当滑动窗口的左侧值对应的value等于deq.front()的话,则目前的队头元素排出,未排出时滑动窗口每移动一下,把这个值存入结果数组中一次。
总结:第一次接触了单调队列的思想,但是对于怎么使用,什么时候使用还没有清晰的认知。
单调队列:队列中的元素按从大到小或者从小到大的顺序排列,push新元素时如果旧元素不符合条件则先pop旧元素再push新元素。
class Solution {
public:
// 双端队列存储当前的值 如果后面进来的值大于前面的所有值
// 那把前面所有的值都出队 如果只大于尾部的值 就把这些值从尾部出队
// 难点:怎么让单调队列随着滑动窗口移动呢
// 其实
// 如果滑动窗口移除的值不等于单调队列里面的值,单调队列就不pop。只有相等时才pop
// 其次push时如果大于队尾元素,则队尾元素出队,该元素入队
// 自己定义一个单调队列
class myqueue {
public:
双端队列
deque<int> deq;
void push( int x) {
// 如果push进入的值大于队尾元素 则队尾元素出队
while (!deq.empty() && x > deq.back()) {
deq.pop_back();
}
deq.push_back(x);
};
void pop(int x) {
// 如果此时队首元素和滑动窗口将要移除的元素相同的话 就出队
if (!deq.empty() && x == deq.front())
deq.pop_front();
};
// 查找目前最大的元素
int front() { return deq.front(); };
};
vector<int> maxSlidingWindow(vector<int>& nums, int k) {
vector<int> ans;
myqueue myq;
//deque<int> deq;
//先确定第一个最大值
int maxval = nums[0];
for(int i=0;i<k;i++){
maxval = max(maxval,nums[i]);
myq.push(nums[i]);
}
ans.push_back(maxval);
for(int i=k;i<nums.size();i++){
myq.push(nums[i]);
myq.pop(nums[i-k]);
ans.push_back(myq.front());
}
return ans;
}
};
347.前 K 个高频元素
遇到的问题:还没搞明白优先级队列的用法和定义;对于大顶堆和小顶堆不了解;不清楚自定义比较函数的使用和定义
思想:map存储每个字母的出现频次后,利用优先级队列将元素进行排序,之后存入容器中。
优先级队列:默认大根堆,如果想实现小根堆则需要自定义函数来改变排序规则,这里需要注意的是存放小根堆的数组是从后往前开始建堆的,所以数组从前到后是一个从大到小的顺序。
class Solution {
public:
//自定义比较函数
class myqueue{
public:
bool operator()(pair<int,int> &pair1,pair<int,int> &pair2){
return pair1.second > pair2.second;
}
};
vector<int> topKFrequent(vector<int>& nums, int k) {
//首先把所有的元素出现频率都数一下 放进map
unordered_map<int,int> temp;
for(int i=0; i<nums.size(); i++){
temp[nums[i]]++;
}
//利用优先级队列进行排序
//因为要留下前k个最大频率的值 所以我们要不断pop掉最小值
priority_queue<pair<int,int>,vector<pair<int,int>>,myqueue> pr_que;
for(unordered_map<int, int>::iterator it=temp.begin();it!=temp.end();it++){
pr_que.push(*it);
if(pr_que.size()>k) pr_que.pop();
}
//此时优先级队列中只剩前k个最大值了
vector<int> ans(k);
for(int i=k-1;i>=0;i--){
ans[i]=pr_que.top().first;
pr_que.pop();
}
return ans;
}
};