https://leetcode-cn.com/problems/largest-rectangle-in-histogram/submissions/
    左右指针优化法:

    1. class Solution {
    2. public int largestRectangleArea(int[] heights) {
    3. // 时间:O(N)
    4. int length = heights.length;
    5. int maxArea = 0;
    6. int[] leftBound = new int[length];
    7. int[] rightBound = new int[length];
    8. for (int i = 0; i < length; i++) {
    9. int height = heights[i];
    10. int left = i - 1;
    11. // 左指针左移,寻找边界
    12. while (left >= 0) {
    13. if (heights[left] < height) break;
    14. // 如果左边柱子更高,就直接跳到它的左边界柱子再判断
    15. left = leftBound[left];
    16. }
    17. leftBound[i] = left;
    18. }
    19. for (int i = length - 1; i >= 0; i--) {
    20. int height = heights[i];
    21. int right = i + 1;
    22. // 右指针右移,寻找边界
    23. while (right < length) {
    24. if (heights[right] < height) break;
    25. // 如果右边柱子更高,就直接跳到它的右边界柱子再判断
    26. right = rightBound[right];
    27. }
    28. rightBound[i] = right;
    29. }
    30. // 遍历所有柱子,计算面积
    31. for (int i = 0; i < length; i++) {
    32. int curArea = (rightBound[i] - leftBound[i] - 1) * heights[i];
    33. maxArea = Math.max(maxArea,curArea);
    34. }
    35. return maxArea;
    36. }
    37. }

    单调栈优化法

    1. class Solution {
    2. public int largestRectangleArea(int[] heights) {
    3. int length = heights.length;
    4. int maxArea = 0;
    5. int[] leftBound = new int[length];
    6. int[] rightBound = new int[length];
    7. for (int i = 0; i < length; i++) {
    8. rightBound[i] = length;
    9. }
    10. LinkedList<Integer> stack = new LinkedList<>();
    11. // 遍历所有柱子,作为当前高度
    12. for (int i = 0; i < length; i++) {
    13. while (!stack.isEmpty() && heights[i] <= heights[stack.peek()]) {
    14. // 当前元素的高度小于栈顶元素,那么此时其右边界就是当前元素
    15. rightBound[stack.peek()] = i;
    16. stack.pop();
    17. }
    18. // 所有大于等于当前高度的元素全部弹出,找到了左边界
    19. leftBound[i] = stack.isEmpty() ? -1 : stack.peek();
    20. stack.push(i);
    21. }
    22. for (int i = 0; i < length; i++) {
    23. int curArea = (rightBound[i] - leftBound[i] - 1) * heights[i];
    24. maxArea = Math.max(maxArea, curArea);
    25. }
    26. return maxArea;
    27. }
    28. }