思路
- 暴力枚举
- 单调栈
暴力枚举
思路
暴力枚举只要依次遍历[i,j]的面积求出最大值即可
双层循环,第一层循环遍历起点,第二层循环遍历终点,每次求出[i,j]取间内矩形的面积
并与当前的最大值进行比较。
取间内面积的求法:
最开始循环该起点时,将该七点的高度作为取间的高度,当后面的矩形的高度低于当前
的取间高度时,进行替换,并计算面积。
代码实现
int main() {
int result = 0;
int arr[N];
//读入数据
int num;
scanf("%d", &num);
for (int i = 0; i < num; i++) {
scanf("%d", &arr[i]);
}
for (int i = 0; i < num; i++) {
int height = arr[i];
for (int j = i; j <= num; j++) {
if (arr[j] < height) {
height = arr[j];
}
result = fmax(result, (j - i + 1) * height);
}
}
printf("%d", result);
return 0;
}
单就该题而言,我认为暴力枚举是容易想也是比较好实现的一种方法。但是当遇到矩形数目很多的情况时,会超时,比如leetcode83,如果使用暴力枚举就会超时,所以这种情况下就该使用单调栈了。
单调栈
规律
通过上述图我们能过发现,什么情况下需要进行计算面积,只要当遍历到该矩形右侧的第一个比它小的矩形时开始计算矩形面积,因此我们能够得出以该矩形为高的矩形右侧边界,那左侧边界呢?从图中可以看出,左侧边界就是该矩形左侧第一个高度比它小的矩形,同时在最左侧和最右侧添加一个0,使得所有的矩形都符合上述规则。
通过上图可以能过看出,在求一个以某一矩形高度为高的矩形的最大面积时,其实求的是该矩形右侧和左侧第一个小于该矩形的矩形,而该特性使用单调栈可以利用
O
(
n
)
O(n)
O(n)的时间求出,因为我们希望出现的是左边稍小,右边稍大,所以采用的是单增栈。
便于确定宽度,此单调栈存储的不是矩形的高度,而是矩形的下标。
代码实现
下面给出力扣上ac的代码,csp只需做一点改动即可。
int largestRectangleArea(vector<int>& heights) {
//前后各添加一个0元素,使用所有元素都符合规则
heights.insert(heights.begin(),0);
heights.insert(heights.end(),0);
int stack[heights.size()+1];
stack[0]=0;
int top=0;
int result=0;
for(int i=0;i<heights.size();i++){
//保持单增栈,当遇到 heights[stack[top]] > heights[i]时,表明遇到了右侧第一个稍小的元素,进行计算
while(top!=0 && heights[stack[top]] > heights[i]){
//矩形高度
int height=heights[stack[top--]];
//矩形左边界:因为是单增栈,所以栈中元素都小于该矩形的高度,当栈顶元素弹出后的栈顶元素就是左侧稍小矩形的下边。
int left=stack[top];
//计算
result=max(result,(i-left-1)*height);
}
stack[++top]=i;
}
return result;
}