题目描述

原题链接

给定 n 个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1 。
求在该柱状图中,能够勾勒出来的矩形的最大面积。

示例 1:
image.png

  1. 输入:heights = [2,1,5,6,2,3]
  2. 输出:10
  3. 解释:最大的矩形为图中红色区域,面积为 10

示例 2:

  1. 输入: heights = [2,4]
  2. 输出: 4

提示:

  • 1 <= heights.length <=105
  • 0 <= heights[i] <= 104

个人解法

Java

JavaScript

更优解法

Java

单调栈

暴力解法我们比较容易想到,我们只要找出每个柱子的左右边界(左右比自己低的第一个柱子或总的边界点)就可以计算出面积。但暴力解法会超时,我们需要优化,两侧的高都知道的话(左右边界确定),宽自然确定。我们首先考虑如何更好地确定左边界,右边界大同小异。
对于一个柱子来说,如果它左边的第一个柱子比自己矮,那这个柱子就是它的左边界。如果比自己高则继续往左找。
736046D0810E9B52A2DF2C34A4D5AB1F.jpg
所以我们利用单调栈来解决问题,栈顶比自己小,直接记录左边界位置,自己入栈;栈顶比自己大,则弹出栈顶元素(找边界的边界(的边界)。。。。。。),一直到找到比自己小的元素,或到了边界-1。

  1. class Solution {
  2. public int largestRectangleArea(int[] heights) {
  3. int len = heights.length;
  4. //用于记录左右边界下标
  5. int[] left = new int[len];
  6. int[] right = new int[len];
  7. Stack<Integer> stack = new Stack<>();
  8. //用-1来表示边界
  9. stack.push(-1);
  10. //如果栈顶比自己小,直接记录左边界(栈顶)位置,自己入栈
  11. for (int i = 0; i < len; i++) {
  12. //栈顶比自己大,则弹出栈顶元素,一直到找到比自己小的元素
  13. while (stack.peek() != -1 && heights[i] <= heights[stack.peek()]) {
  14. stack.pop();
  15. }
  16. left[i] = stack.peek();
  17. stack.push(i);
  18. }
  19. //右边界寻找方法类似,不过右边界如果为最右边要存入len下标而不是-1
  20. stack = new Stack<>();
  21. stack.push(-1);
  22. for (int i = len-1; i >=0; i--) {
  23. while (stack.peek() != -1 && heights[i] <= heights[stack.peek()]) {
  24. stack.pop();
  25. }
  26. if (stack.peek()==-1){
  27. right[i]=len;
  28. }else {
  29. right[i] = stack.peek();
  30. }
  31. stack.push(i);
  32. }
  33. int max=-1;
  34. //遍历找到最大矩形
  35. for (int i=0;i<len;i++){
  36. max=Math.max(max,(right[i]-left[i]-1)*heights[i]);
  37. }
  38. return max;
  39. }
  40. }

JavaScript