150. 逆波兰表达式求值
这题难点在于找到其中规律并进行模拟。有了思路后整体不难,另外这里得掌握stoi函数和to_string函数。
class Solution {
public:
int calculate(int num1,int num2,const string& s) {
if(s == "+") return num1 + num2;
if(s == "-") return num1 - num2;
if(s == "*") return num1 * num2;
if(s == "/") return num1 / num2;//应该判断num2是否为0,这里测试能通过就不判断了
return -1;
}
int evalRPN(vector<string>& tokens) {
stack<int> stk;
int num1, num2, res;
for(auto ch:tokens) {
if(ch=="+" || ch=="-" || ch=="*" || ch=="/") {
num2 = stk.top();
stk.pop();
num1 = stk.top();
stk.pop();
res = calculate(num1,num2,ch);
stk.push(res);
}else{
stk.push(stoi(ch));
}
}
return stk.top();
}
};
239. 滑动窗口最大值
这题开始用的暴力求解法,但是时间复杂度为O(k*n)太高,看了解题思路后醍醐灌顶。滑动窗口可以等效为双向队列尾部插入(push_back)一个元素,队首弹出(pop)一个元素。deque是我们的理想数据结构,但它没法直接求出队列中的最大元素。所以这里要创建一个数据结构,要求是:1. push和pop的时间复杂度皆为O(1)。2. 保持队首元素永远最大。
按照要求我们创建了Myque,提示:1. 后一个元素如果比前面的元素大,那么前面的元素一定要舍弃。2. 弹出左指针对应的元素,因为左指针右移,之前指向的元素超过了滑动窗口边界。
class Solution {
public:
//创造一个数据结构,使队首元素永远最大
struct Myque{
deque<int> que;
void push(int value){
while(!que.empty() && value > que.back()){
que.pop_back();
}
que.push_back(value);
}
void pop(int value){
if(!que.empty() && que.front() == value) {
que.pop_front();
}
}
int top(){
return que.front();
}
};
vector<int> maxSlidingWindow(vector<int>& nums, int k) {
Myque que;
vector<int> result;
for(int i = 0; i < k; ++i) {
que.push(nums[i]);
}
result.push_back(que.top());
for(int i = k; i <nums.size(); ++i) {
que.pop(nums[i-k]);
que.push(nums[i]);
result.push_back(que.top());
}
return result;
}
};
347.前 K 个高频元素
这题要结合unordered_map(统计出现次数)和priority_queue(对出现次数排序)。大堆顶(堆顶值最大,然后逐步减小)和小堆顶(堆顶值最小,然后逐步增大)很难记,每次用都得查一下它比较器的顺序。比较器返回true表示优先级较低,举例:
下图比较器left.second > right.second返回true,表示左边元素优先级较低(即更大的值放在更低的位置),即是小顶堆。
auto compare = [](pair<int,int> left, pair<int,int> right){
return left.second > right.second;
};
class Solution {
public:
vector<int> topKFrequent(vector<int>& nums, int k) {
auto compare = [](pair<int,int> left, pair<int,int> right){
return left.second > right.second;
};
unordered_map<int,int> umap;
for(auto n:nums) {
umap[n]++;
}
//小顶堆(堆顶到堆底元素逐渐变大)
priority_queue<pair<int,int>, vector<pair<int,int>>,decltype(compare)> preQue;
for(auto it = umap.begin();it!=umap.end();++it) {
preQue.push(*it);
if(preQue.size() > k)
preQue.pop();//弹出最小的元素
}
vector<int> res(k);
for(int i = k-1; i >= 0; i--) {
res[i] = preQue.top().first;
preQue.pop();
}
return res;
}
};