利用栈求解逆波兰表达式,注意,这个逆波兰表达式是输入合法的,并没有对不合法情况进行判定,所以代码的健壮性存在欠缺,而且演算符缺少!,想要更加详细地学习逆波兰表达式的处理,可以参考邓俊辉老师的数据结构,栈那个章节内容。
public:
int evalRPN(vector<string>& tokens) {
// 空表达式直接返回0(题目不会出现空输入,仅做鲁棒性处理)
if (tokens.empty()) return 0;
// 用栈存储数字,逆波兰表达式的核心数据结构
stack<int> numStack;
for (const string& token : tokens) {
// 判断是否是运算符
if (token == "+" || token == "-" || token == "*" || token == "/") {
// 弹出栈顶两个操作数(注意顺序!)
int num2 = numStack.top(); // 第一个弹出的是右操作数
numStack.pop();
int num1 = numStack.top(); // 第二个弹出的是左操作数
numStack.pop();
// 根据运算符计算,结果重新入栈
if (token == "+") {
numStack.push(num1 + num2);
} else if (token == "-") {
numStack.push(num1 - num2);
} else if (token == "*") {
numStack.push(num1 * num2);
} else if (token == "/") {
// 整数除法,题目要求向零取整(C++默认就是,无需额外处理)
numStack.push(num1 / num2);
}
} else {
// 是数字,转换为int后入栈
numStack.push(stoi(token));
}
}
// 最终栈中只剩一个数,就是结果
return numStack.top();
}
};
单调队列求滑动窗口最大值。 1.滑动窗口应当设计为双端队列,如果使用单端队列的话,在保持队列单调时,要额外设置max记录处理 2.应当注意到,使用单调队列时,最大值始终在队列顶部。
public:
vector<int> maxSlidingWindow(vector<int>& nums, int k) {
// 处理边界情况:数组为空或窗口大小为0/1
if (nums.empty() || k <= 0) return {};
if (k == 1) return nums;
vector<int> result; // 存储每个窗口的最大值
deque<int> monoDeque; // 单调递减队列,存储nums的下标
for (int i = 0; i < nums.size(); ++i) {
// 1. 移除队列中超出当前窗口范围的下标(窗口左边界:i - k + 1)
while (!monoDeque.empty() && monoDeque.front() < i - k + 1) {
monoDeque.pop_front();
}
// 2. 移除队列尾部所有比当前元素小的下标(保证队列单调递减)
// 因为当前元素更大,之前的小元素不可能成为后续窗口的最大值
while (!monoDeque.empty() && nums[i] > nums[monoDeque.back()]) {
monoDeque.pop_back();
}
// 3. 将当前元素下标入队
monoDeque.push_back(i);
// 4. 从第k-1个元素开始(窗口首次形成),记录每个窗口的最大值(队首)
if (i >= k - 1) {
result.push_back(nums[monoDeque.front()]);
}
}
return result;
}
};
347,前k个高频元素的选取。 1.使用hash表统计出现频率 2.将hash表转变为堆
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) {
//使用哈希表统计出现频率,采用map
unordered_map<int,int>map;
for(int i=0;i<nums.size();i++){
map[nums[i]]++;
}
//将map转换为优先级队列
priority_queue<pair<int, int>, vector<pair<int, int>>, mycomparison> pri_que;
// 用固定大小为k的小顶堆,扫面所有频率的数值
for (unordered_map<int, int>::iterator it = map.begin(); it != map.end(); it++) {
pri_que.push(*it);
if (pri_que.size() > k) { // 如果堆的大小大于了K,则队列弹出,保证堆的大小一直为k
pri_que.pop();
}
}
// 找出前K个高频元素,因为小顶堆先弹出的是最小的,所以倒序来输出到数组
vector<int> result(k);
for (int i = k - 1; i >= 0; i--) {
result[i] = pri_que.top().first;
pri_que.pop();
}
return result;
}
};