单调栈
84.柱状图中最大的矩形
https://leetcode.cn/problems/largest-rectangle-in-histogram/
单调栈题目思维套路:
- 确定递增递减一关键在于考虑“前面不能影响到后面”的条件
- 本题中若h[i-1]> h[i], 则h[i- 1]这个高度就无法影响到更后面,自然可以单独计算了
单调栈题目代码套路:
- for 每个元素
-
while (栈顶与新元素不满足单调性) {弹栈,更新答案,累加“宽度”}
-
入栈
class Solution {
public:
int largestRectangleArea(vector<int>& heights) {
int ans=0;
heights.push_back(0);
for(int height: heights){
int accumulateWidth = 0;
while(!s.empty() && s.top().height >= height){
accumulateWidth+=s.top().width;
ans = max(ans,s.top().height * accumulateWidth);
s.pop();
}
s.push({accumulateWidth+1,height});
}
return ans;
}
private:
struct Rect{
int width;
int height;
};
stack<Rect> s;
};
单调队列
239.滑动窗口最大值
https://leetcode.cn/problems/sliding-window-maximum/
单调队列题目思维套路:
- 单调队列维护的是一个候选集合,前面的比较旧,后面的比较新(时间有单调性)
- 候选项的某个属性也具有单调性
- 确定递增递减的方法一考 虑任意两个候选项j1<jz,写出j比jz优的条件
排除冗余的关键:若j1比j2差,j1 的生命周期还比j2短,那j1就没卵用了
单调队列题目代码套路:
- for每个元素
-
(1) while (队头过期)队头出队
-
(2)取队头为最佳选项,计算答案
-
(3) while (队尾与新元素不满足单调性)队尾出队
-
(3)新元素入队
(2) (3)的顺序取决于:
i是不是候选项
class Solution {
public:
vector<int> maxSlidingWindow(vector<int>& nums, int k) {
vector<int> ans;
for(int i=0;i<nums.size();i++){
q.push({nums[i],i});
if(i >= k-1){
while(q.top().second <= i-k) q.pop();
ans.push_back(q.top().first);
}
}
return ans;
}
private:
priority_queue<pair<int,int>> q;
};
42.接雨水
https://leetcode.cn/problems/trapping-rain-water/
class Solution {
public:
int trap(vector<int>& height) {
int ans = 0;
int left = 0, right = height.size() - 1;
int leftMax = 0, rightMax = 0;
while (left < right) {
leftMax = max(leftMax, height[left]);
rightMax = max(rightMax, height[right]);
if (height[left] < height[right]) {
ans += leftMax - height[left];
++left;
} else {
ans += rightMax - height[right];
--right;
}
}
return ans;
}
};
class Solution {
public:
int trap(vector<int>& heights) {
int ans =0;
for(int height : heights){
int accmulateWidth=0;
while(!s.empty() && s.top().height <= height){
int bottom = s.top().height;
accmulateWidth += s.top().width;
s.pop();
if (s.empty()) continue;
//int up = s.empty() ? 0 : min(height,s.top().height);
int up = min(height,s.top().height);
//if(!s.empty() && s.top().height < up) up = s.top().height;
ans += accmulateWidth * (up - bottom);
}
s.push({accmulateWidth + 1,height});
}
return ans;
}
private:
struct Rect{
int width;
int height;
};
stack<Rect> s;
};
class Solution {
public:
int trap(vector<int>& heights) {
int n=heights.size();
preMax = vector<int>(n);
sufMax = vector<int>(n);
preMax[0] = heights[0];
for(int i=1;i<n;i++) preMax[i] = max(preMax[i-1],heights[i]);
sufMax[n-1] = heights[n-1];
for(int i = n-2;i >= 0;i--) sufMax[i] = max(sufMax[i+1],heights[i]);
int ans = 0;
for(int i=1;i < n-1;i++)
{
int up = min(preMax[i-1],sufMax[i+1]);
int bottom = heights[i];
if(up > bottom) ans+=up - bottom;
}
return ans;
}
private:
vector<int> preMax;
vector<int> sufMax;
};
推荐一个零声学院免费公开课程,个人觉得老师讲得不错,分享给大家:Linux,Nginx,ZeroMQ,MySQL,Redis,fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,TCP/IP,协程,DPDK等技术内容,立即学习