84. Largest Rectangle in Histogram

Problem statment:

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.

Above is a histogram where width of each bar is 1, given height = [2,1,5,6,2,3].

The largest rectangle is shown in the shaded area, which has area = 10 unit.

For example, Given heights = [2,1,5,6,2,3], return 10.

Solutions one:

Intuitively, brute force is the first solution of most people(includeing me), the time complexity is very high(O(n*n*n), n is the size of input). It is no doubt that OJ submission will fail. A smart move to solve this problem is stack. But, it is hard to figure it out.

Compared with storing the value of heights, each element in stack is the index of heights. Because we need to calculate the area, index is helpful for us to calculate the length.

The policy for push in and pop from the stack is:

(stack is empty  || current_value  >= stack.top()) --> push in to stack

otherwist, pop from stack and update the max area.

There is a tricky is essential, we need add a zero to the end of heights, otherwise, we can not get the right answer. The purpose is to pop all element from stack and update the max area.

For example, if the stack is <1, 2, 3, 0>(for illustration purpose, actually stack stores the index). When for loop gets to 0, current position is 7. The processing is as following:

  • 3(index is 6) is popped from the stack, the element in front of 3 is 2(index is 5), it means the minimum height after 2 to end is 3. The length is 7 - 5 - 1, max area is 3.
  • Then, 2 is popped from the stack, the element in front of 2 is 1(index is 1). it means the minimum height after 1, till end is 2. the length is 7 - 1 - 1. we get the maximum area is 2 * 5 = 10.
  • In the end, 1 is poped from the stack, it is the minimum height in this array and stack is empty, the total length is 7, which is the length of the array.

class Solution {
public:
    int largestRectangleArea(vector<int>& heights) {
        if(heights.empty()){
            return 0;
        }
        heights.push_back(0);
        stack<int> stk; // idx
        int max_area = 0;
        for(int ix = 0; ix < heights.size(); ix++){
            if(stk.empty() || heights[ix] >= heights[stk.top()]){
                stk.push(ix);    
            } else {
                while(!stk.empty() && heights[stk.top()] > heights[ix] ){
                    int idx = stk.top();
                    stk.pop();
                    max_area = max(max_area, heights[idx] * (stk.empty()? ix : ix - stk.top() - 1));   
                }
                stk.push(ix);
            } 
        }
        return max_area;
    }
};

Solution two:

This solution from online articles. I like this solutions, it is simple to understand and easy to implement. loops to find a local max value, and goes back  to update the max area. No extra data structure.

class Solution {
public:
    int largestRectangleArea(vector<int>& heights) {
        int max_area = 0;
        for(int i = 0; i < heights.size(); i++){
            if(i + 1 < heights.size() && heights[i] <= heights[i + 1]){
                continue;
            } else {
                // find a local maximum value
                // loop back to update max area
                int min_height = INT_MAX;
                int cur_area = 0;
                // loop back to find the update the max area
                for(int j = i; j >= 0; j--){
                    min_height = min(min_height, heights[j]);
                    max_area = max(max_area, min_height * (i - j + 1));
                }
            }
            
        }
        return max_area;
    }
};

Time complexity comparison:

Although like the second solution, the drawback is obvious. The time complexity is O(n*n).

  • In best case, such as ascending array, the  time complexity is O(n) since the local maxi value is the last one, and then loop back until to the start.
  • But, in worse case, such as descending array, the time complexity is O(n * n).

For solution one, there is an extra stack data structure, but the time complexity is O(n).

  • Loop to the end of the array.
  • For each element, they will be pushed in and popped out from the stack only once, the total time complexity is O(n).
原文地址:https://www.cnblogs.com/wdw828/p/6848177.html