任务日期:7.24
题目一链接:42. 接雨水 - 力扣(LeetCode)
思路:本题利用单调栈寻找任一一个元素右侧第一个比他大的元素的位置,而左侧我们用当前元素左侧的那个元素,从而形成一个凹槽(根据单调栈的性质,一定是一个凹槽,只不过宽度可能不是1),然后利用公式求出结果。
代码:
class Solution {
public:
//从左到右遍历数组下标
//本题公式:h = (min(左侧柱子高度,右侧柱子高度) - mid) * w(右侧最高度和左侧最高度所对应的下标差值),然后多个h相加即得结果
int trap(vector<int>& height) {
stack<int> st;
st.push(0);
int res = 0;
for(int i = 1;i < height.size();i ++) {
if(height[i] < height[st.top()]) {
st.push(i);
}
else if(height[i] == height[st.top()]) {
st.pop();
st.push(i);
}
else { //当前元素大于栈顶元素时:此时形成凹槽,即栈顶和栈顶的下一个元素以及要入栈的元素,三个元素来接水:根据单调栈的性质,此时一定能形成凹槽
while(!st.empty() && height[i] > height[st.top()]) { 注意这里是while,持续跟新栈顶元素
int mid = height[st.top()];//先记录中间元素的高度mid
st.pop();//将中间元素弹出
if(!st.empty()) { //这里需要判断一下是否为空:如果是空的则不用后续计算了
int h = min(height[st.top()],height[i]) - mid;
int w = i - st.top() - 1; //这里求的是距离所以要减一
res += h * w;
}
}
st.push(i);
}
}
return res;
}
};
难点:1.在从左向遍历元素时,如果当前元素小于栈顶元素则直接入栈,等于栈顶元素时则弹出栈顶元素将当前元素入栈。
2.当当前元素大于栈顶元素时,我们利用while循环持续更新栈顶元素进行计算,因为可能进行
3.进入while循环后先记录当前栈顶元素的高度mid用于计算成水的体积:高度乘以宽度,这里的高度取而这较小值然后减去当前栈顶元素的高度。
4.在弹出栈顶元素后需要判断栈是否为空,而此时的栈顶元素对应的高度就是当前点的左侧高度值,然后利用公式求值:h = min(height[st.top()],height[i]) - mid,w = i - st.top() - 1,这里求的是距离所以要减一。
题目二链接:84. 柱状图中最大的矩形 - 力扣(LeetCode)
思路:本题和上一题的本质区别有两点:
1.**本题需要在数组末尾和开头加俩零**,确保在数组单调的情况下仍然能形成凹槽,并最终把每个数都代入公式里求出最大值。
2.本题用h * w所以即使不能形成凹槽也需要进行计算求得结果,因此这也是有1.的原因
共同点:
都是寻找右侧第一个或大或小的值,然后形成凹或凸槽然后带入公式计算。
代码:
class Solution {
public:
//公式:s = hight[mid] * (i - st.top()),理解公式就明白思路了
int largestRectangleArea(vector<int>& heights) {
stack<int> st;
st.push(0);
int res = 0;
//在数组的开头和结尾加上俩零,确保在数组单调的情况下仍然能进行计算,并最终把每个数都代入公式里求出最大值。
heights.insert(heights.begin(),0);
heights.push_back(0);
for(int i = 1;i < heights.size();i ++) {
if(heights[i] > heights[st.top()]) {
st.push(i);
}
else if(heights[i] == heights[st.top()]) {
st.pop();
st.push(i);
}
else {
while(!st.empty() && heights[i] < heights[st.top()]) { //while循环因为要进行多次
int mid = heights[st.top()];
st.pop();
if(!st.empty()) {//如果pop()完不为空才利用那个最典型的凹槽计算
int l = st.top();//左边界就是st栈顶元素的下标
int r = i;
int w = r - l - 1;
int h = mid;
res = max(res,w * h);//最大值
}
}
st.push(i);
}
}
return res;
}
};
难点:1.本题的公式是:res = h * w;h是凹槽中间柱子的高度,w则是两边柱子(**这俩柱子不一定挨着,这里是关键**)的下标差 - 1.