150. 逆波兰表达式求值
逆波兰表达式:是一种后缀表达式,所谓后缀就是指运算符写在后面。
计算机可以利用栈来顺序处理,不需要考虑优先级了。也不用回退了, 所以后缀表达式对计算机来说是非常友好的。
class Solution {
public:
int evalRPN(vector<string>& tokens) {
stack<long long> st;
for(auto c:tokens){
if(c=="+"||c=="/"||c=="*"||c=="-"){
long long num1 = st.top();
st.pop();
long long num2 = st.top(); //这个才是前面的那个数
st.pop();
if(c=="+") st.push(num1+num2);
if(c=="-") st.push(num2-num1);
if(c=="*") st.push(num1*num2);
if(c=="/") st.push(num2/num1);
}else{
st.push(stoll(c));
}
}
return st.top();
}
};
- 时间复杂度: O(n)
- 空间复杂度: O(n)
239. 滑动窗口最大值
给定一个数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。
返回滑动窗口中的最大值。
使用单调队列的经典题目。
如果使用暴力方法,该算法的复杂度O(n*k)。
class Solution {
private:
class MyQueue{ //单调队列,从大到小
public:
deque<int> que; // 使用deque来实现单调队列 double-ended queue. for which elements can be added to or removed from either the front (head) or back (tail)
void pop(int value){
//每次弹出的时候比较需要弹出的数是不是队列口的数
if(!que.empty()&&value==que.front()){
que.pop_front();
}
}
//如果push的数值大于入口元素,那么将队列后端的数值弹出(因为知道这个数肯定不会被用到了),直到push的数值小于等于队列入口元素的数值为止
void push(int value){
while(!que.empty()&&value>que.back()){//直到这个数不比que的最后一个数小
que.pop_back();
}
que.push_back(value);
}
//查询当前队列里的最大值,直接返回队列前端
int front(){
return que.front();
}
};
public:
// 写一个单调栈列
vector<int> maxSlidingWindow(vector<int>& nums, int k) {
MyQueue que;
vector<int> result;
for(int i=0; i<k; i++){ //先将前k个元素放进队列
que.push(nums[i]);
}
result.push_back(que.front());
for(int i=k; i<nums.size(); i++){
que.pop(nums[i-k]); //滑动窗口移除最前面的元素
que.push(nums[i]);//滑动窗口前加入最后面的元素
result.push_back(que.front());
}
return result;
}
};
- 时间复杂度: O(n)
- 空间复杂度: O(k)
二刷的时候试者自己再写一次
347.前 K 个高频元素
给定一个非空的整数数组,返回其中出现频率前 k 高的元素。
- 要统计元素出现频率:考虑map
- 对频率排序:优先级队列
- 找出前K个高频元素
什么是优先级队列priority_queue?