LeetCode--84.柱状图中最大的矩形(暴力法,单调栈)

柱状图中最大的矩形(暴力法,单调栈)

1. 题目描述

难度:困难
在这里插入图片描述
在这里插入图片描述

2. 题目分析

这道题有两种解法,一种是暴力遍历法,一种是利用栈来进行的单调栈的方法。
- 暴力法
暴力法师很容易想到的方法,从左到右依次遍历数组,依次计算每个元素所构成的最大矩形面积。时间复杂度为O(n^2)。
- 单调栈
这是一个非常典型的利用单调栈来解决 顺序和大小综合问题的题。单调栈特别适合解决这些,两头大小决定中间值的大小的题。
因为单调栈中,以单调增栈为例。
设栈顶元素为 b, 栈顶第二个元素为a,自然有 a < b (因为堆栈越往上越大),这时候, 若c出现,且c小于b, 那么b的左右第一个比b小的两个元素就找到了,分别是a和c,b在中间最大。这时候你可以处理b,并重新整理堆栈,使其保持递增。若c大于b,那c入栈,继续循环就行了。最后清理堆栈。
这个题的关键点在于:
以B点为高的矩形的最大宽度为, 从a到c, 其中a,c分别为B左边和右边第一个小于B的元素。
单调栈的特点在于:
当遇见大数的时候, 压入堆栈,等待之后处理。
当遇见小数c的时候,意味着大数b的右边界c已经确定了。

这时候开始pop, 而以被pop出来的值(b)为高度的矩形的左右边界需要被确定。
其右边界就是当前的小数。即为c。左边界是堆栈下一层的元素,因为下一层的元素一定比当前小。且是第一小的元素。这时候a也确定了。
则以被pop出来的数为高度的矩形是 (c - a - 1) * pop(), 这里pop() == b
这里细节需要注意的是,

  • 栈底要垫上**-1**,表示栈底。
  • 循环结束,要清理堆栈。此时所有栈中继续存放的元素的右边界c都是结尾len(height)-1

3. C语言实现

3.1 暴力法
// 暴力法
int largestRectangleArea(int* heights, int heightsSize){
    int i, j;
    int max = 0;
    int minHeight;
    if(heightsSize == 1) return heights[0];
    if(heightsSize == 0) return 0;
    for(i = 0; i < heightsSize; i++){
        minHeight = heights[i];
        for(j = i; j < heightsSize; j++){
            minHeight = minHeight < heights[j]? minHeight:heights[j];
            max = max > minHeight*(j-i+1)? max: minHeight*(j-i+1);
        }
    }
    return max;
}

运行结果为:
在这里插入图片描述

3.2 单调栈

代码如下:

int returnMax(int a, int b){
    return a>b?a:b;
}
// 单调栈
int largestRectangleArea(int* heights, int heightsSize){
    if(heightsSize == 0) return 0;
    if(heightsSize == 1) return heights[0];
    int* stack = (int *)malloc(sizeof(int)*(heightsSize+1));
    int index = 0;
    int max = 0;
    int label;
    stack[index] = -1;
    for(int i = 0; i < heightsSize; i++){
        while(index != 0 && heights[i] < heights[stack[index]]){
            max = returnMax(max, heights[stack[index]]*(i-stack[--index]-1));
        }
        stack[++index] = i;
    }
    label = index;
    while(index != 0){
        max = returnMax(max, heights[stack[index]]*(stack[label]-stack[--index]));
    }
    return max;
}

运行结果为:
在这里插入图片描述

4. Java实现

单调栈代码实现如下:

public class Solution {
    public int largestRectangleArea(int[] heights) {
        Stack < Integer > stack = new Stack < > ();
        stack.push(-1);
        int maxarea = 0;
        for (int i = 0; i < heights.length; ++i) {
            while (stack.peek() != -1 && heights[stack.peek()] >= heights[i])
                maxarea = Math.max(maxarea, heights[stack.pop()] * (i - stack.peek() - 1));
            stack.push(i);
        }
        while (stack.peek() != -1)
            maxarea = Math.max(maxarea, heights[stack.pop()] * (heights.length - stack.peek() -1));
        return maxarea;
    }
}

运行结果为:
在这里插入图片描述

发布了163 篇原创文章 · 获赞 188 · 访问量 12万+

猜你喜欢

转载自blog.csdn.net/qq_42580947/article/details/105101686