Maximize the rectangular area under Histogram

前端 未结 11 839
天涯浪人
天涯浪人 2020-11-28 17:26

I have a histogram with integer heights and constant width 1. I want to maximize the rectangular area under a histogram. e.g.:

 _
| |
| |_ 
|   |
|   |_
|           


        
11条回答
  •  攒了一身酷
    2020-11-28 18:02

    I would like to thank @templatetypedef for his/her extremely detailed and intuitive answer. The Java code below is based on his suggestion to use Cartesian Trees and solves the problem in O(N) time and O(N) space. I suggest that you read @templatetypedef's answer above before reading the code below. The code is given in the format of the solution to the problem at leetcode: https://leetcode.com/problems/largest-rectangle-in-histogram/description/ and passes all 96 test cases.

    class Solution {
    
    private class Node {
        int val;
        Node left;
        Node right;
        int index;
    }
    
    public  Node getCartesianTreeFromArray(int [] nums) {
        Node root = null;
        Stack s = new Stack<>();
        for(int i = 0; i < nums.length; i++) {
            int curr = nums[i];
            Node lastJumpedOver = null;
            while(!s.empty() && s.peek().val >= curr) {
                lastJumpedOver = s.pop();
            }
            Node currNode = this.new Node();
            currNode.val = curr;
            currNode.index = i;
            if(s.isEmpty()) {
                root = currNode;
            }
            else {
                s.peek().right = currNode;
            }
            currNode.left = lastJumpedOver;
            s.push(currNode);
        }
        return root;
    }
    
    public int largestRectangleUnder(int low, int high, Node root, int [] nums) {
        /* Base case: If the range is empty, the biggest rectangle we
         * can fit is the empty rectangle.
         */
        if(root == null) return 0;
    
        if (low == high) {
            if(0 <= low && low <= nums.length - 1) {
                return nums[low];
            }
            return 0;
        }
    
        /* Assume the Cartesian tree nodes are annotated with their
         * positions in the original array.
         */
        int leftArea = -1 , rightArea= -1;
        if(root.left != null) {
            leftArea = largestRectangleUnder(low, root.index - 1 , root.left, nums);
        }
        if(root.right != null) {
            rightArea = largestRectangleUnder(root.index + 1, high,root.right, nums);
        }
        return Math.max((high - low  + 1) * root.val, 
               Math.max(leftArea, rightArea));
    }
    
    public int largestRectangleArea(int[] heights) {
        if(heights == null || heights.length == 0 ) {
            return 0;
        }
        if(heights.length == 1) {
            return heights[0];
        }
        Node root = getCartesianTreeFromArray(heights);
        return largestRectangleUnder(0, heights.length - 1, root, heights);
    }
    

    }

提交回复
热议问题