Jerry's Blog

Recording what I learned everyday

View on GitHub


15 September 2020

LeetCode(84) -- Largest Rectangle in Histogram (Segment Tree)

by Jerry Zhang

Problem

Given n non-negative integers representing the histogram’s bar height where the width of each bar is 1, find the area of largest rectangle in the histogram.

Solution

方法四:线段树

线段树是用一个完全二叉树来存储对应于其每一个区间(segment)的数据

class Solution {
    
    class SegTreeNode {
        int start;
        int end;
        int min;
        SegTreeNode left;
        SegTreeNode right;
        public SegTreeNode(int start, int end) {
            this.start = start;
            this.end = end;
        }
    }
    
    public int largestRectangleArea(int[] heights) {
        if (heights.length == 0) {
            return 0;
        }
        SegTreeNode root = buildSegmentTree(heights, 0, heights.length - 1);
        
        return calculateMax(heights, root, 0, heights.length - 1);
    }
    
    public int calculateMax(int[] heights, SegTreeNode root, int start, int end) {
        if (start > end) {
            return -1;
        }
        if (start == end) {
            return heights[start];
        }
        int minIndex = query(root, heights, start, end);
        int leftMax = calculateMax(heights, root, start, minIndex - 1);
        int rightMax = calculateMax(heights, root, minIndex + 1, end);
        int minMax = heights[minIndex] * (end - start + 1);
        return Math.max(Math.max(leftMax, rightMax), minMax);
    }
    
    public SegTreeNode buildSegmentTree(int[] heights, int start, int end) {
        if (start > end) return null;
        SegTreeNode root = new SegTreeNode(start, end);
        if (start == end) {
            root.min = start;
            return root;
        } else {
            int middle = (start + end) / 2;
            root.left = buildSegmentTree(heights, start, middle);
            root.right = buildSegmentTree(heights, middle + 1, end);
            root.min = heights[root.left.min] < heights[root.right.min] ? root.left.min : root.right.min;
            return root;
        }
    }
    
    public int query(SegTreeNode root, int[] heights, int start, int end) {
        if (root == null || end < root.start || start > root.end) return -1;
        if (start <= root.start && end >= root.end) {
            return root.min;
        }
        int leftMin = query(root.left, heights, start, end);
        int rightMin = query(root.right, heights, start, end);
        if (leftMin == -1) return rightMin;
        if (rightMin == -1) return leftMin;
        return heights[leftMin] < heights[rightMin] ? leftMin : rightMin;
    }
}
tags: LeetCode