150. 逆波兰表达式求值
这一题和删除相邻重复项与判断括号一样,遇到数字入栈,遇到操作符出栈两个数字,然后入栈结果。
因此,栈很适合处理字符串相邻处理。
class Solution {
public:
int evalRPN(vector<string>& tokens) {
stack<long long> st;
for (string c : tokens) {
if (c == "+" || c == "-" || c == "*" || c == "/") {
int num1 = st.top();
st.pop();
int num2 = st.top();
st.pop();
if (c == "+")
st.push(num1 + num2);
else if (c == "-")
st.push(num2 - num1);
else if (c == "*")
st.push(num2 * num1);
else
st.push(num2 / num1);
}
else
st.push(stoll(c));
}
return st.top();
}
};
239. 滑动窗口最大值
如果使用暴力算法,每一个滑动窗口都求最大值,时间复杂度为 O ( n ∗ k ) O(n*k) O(n∗k)。
如何优化呢?维护一个最大长度为k的单调列表,每一次滑动窗口,先将新元素push进来,然后将可能存在的就元素pop出去,队列口就是该窗口最大值。
class Solution {
public:
class MyPriQue{
public:
deque<int> deq;
void pop(int num) {
if (!deq.empty() && deq.front() == num)
deq.pop_front();
}
void push(int num) {
while (!deq.empty() && deq.back() < num)
deq.pop_back();
deq.push_back(num);
}
int getMax() {
return deq.front();
}
};
vector<int> maxSlidingWindow(vector<int>& nums, int k) {
vector<int> result;
MyPriQue que;
for (int i = 0; i < k; ++i) {
que.push(nums[i]);
}
result.push_back(que.getMax());
for (int i = k; i < nums.size(); ++i) {
que.push(nums[i]);
que.pop(nums[i-k]);
result.push_back(que.getMax());
}
return result;
}
};
347. 前 K 个高频元素
- 通过map先计算整数数组中每个元素的频率
- 遍历map,并用priority queue维护大小为k的列表。
- 由于priority queue是小顶堆,因此倒叙输出列表元素。
class Solution {
public:
class mycomparison {
public:
bool operator()(const pair<int, int>& lhs, const pair<int, int>& rhs) {
return lhs.second > rhs.second;
}
};
vector<int> topKFrequent(vector<int>& nums, int k) {
unordered_map<int, int> map;
for (int num : nums)
map[num]++;
priority_queue<pair<int, int>, vector<pair<int, int>>, mycomparison> priQue;
for (auto it = map.begin(); it != map.end(); it++) {
priQue.push(*it);
if (priQue.size() > k)
priQue.pop();
}
vector<int> result(k);
for (int i = k - 1; i >= 0; --i) {
result[i] = priQue.top().first;
priQue.pop();
}
return result;
}
};