[Algorithm question] Maximum rectangular area, monotone stack solution

Force button: 84. The largest rectangle in the histogram

Given n non-negative integers, used to represent the height of each column in the histogram. Each column is adjacent to each other and has a width of 1.
Find the maximum area of ​​the rectangle that can be outlined in the histogram.
insert image description here

The meaning of the question is very simple, the translation is: find the area of ​​the largest rectangle in the figure.

Then, the idea of ​​this question is to traverse. But how to traverse efficiently is a science.
My 单调栈solution to this problem.

The monotonic stack is to maintain a monotonic sequence in the stack.

For this problem, we can maintain a monotonically increasing sequence.
When the element is smaller than the top element of the stack, pop the top element out of the stack until the top element of the stack is smaller than the element, or the stack is empty.
insert image description here
insert image description here

Why maintain a monotonically increasing sequence?

Since the sequence is increasing, the largest rectangle will be very long and it is easy to calculate the area of ​​the largest rectangle.
insert image description here
Take this rectangle as an example
The largest rectangle with a height of 2 is 2 * 4 = 4; the
largest rectangle with a height of 3 is 3 * 3 = 9;
the largest rectangle with a height of 4 is 4 * 2 = 8
; The largest rectangle with height is 5 * 1 = 1;

Then someone is going to ask, some smart cerebellar tubes are going to ask, oops.
In fact, there are rectangles in the middle of some rectangles, which are not real sequential sequences. Will it affect it?
insert image description here

If the original image is like this, then the incremental graph maintained after popping corresponds to the above image. Since the middle 4 is greater than 3 and also greater than 2, the middle rectangle should be the largest, and 4 can be regarded as 3. We can take the opportunity of popping the stack to calculate the area of ​​the rectangle
and use this picture to describe the problem-solving language:
1: The stack is empty, and rectangle 0 is pushed onto the stack. At this time, the rectangle in the stack is: 0
2: The height of rectangle 1 is 4, which is greater than the top element 2 of the stack. Put rectangle 1 on the stack, and the rectangle in the stack is 0, 1 3
: The height of rectangle 2 is 3, and 3 is smaller than the stack The height of the top element is 4, so the top rectangle 1 is popped out of the stack, and the maximum
rectangle with the height of rectangle 1 is calculated at the same time, which is 4 * 1 = 4; at the same time, 3 is pushed into the stack, and the rectangle in the stack is: 0, 2
4: because The height of rectangle 3 is greater than the height of rectangle 2 at the top of the stack, so rectangle 3 is pushed onto the stack. At this time, the rectangles in the stack are: 0, 2, 3
5: Because the height of rectangle 4 is greater than the height of rectangle 3 at the top of the stack, rectangle 4 is placed Push into the stack, the rectangle in the stack at this time is: 0, 2, 3, 4
6. At this time, all the elements have been pushed into the stack, and the elements in the stack are address rectangles, and all the values ​​can be calculated by popping out the stack one by one. Stack, that is, when the stack reaches 3, you cannot directly subtract the serial number of 4 rectangles from the serial number of 2 x + 1, because there may be x xing in front of rectangle 2, you should pick up after rectangle 0 and before rectangle 2.

Realization of JAVA code

class Solution {
    
    
    public int largestRectangleArea(int[] heights) {
    
    

       
        int maxS = 0;
        Stack<Integer> st = new Stack<>();
        //添加矩形入栈
        for(int i = 0; i < heights.length; i++){
    
    
            if(st.empty() || heights[i] >= heights[st.peek()]){
    
    
                st.push(i);
            }else{
    
    
                while(!st.empty() && heights[st.peek()] > heights[i]){
    
    

                        int tempH2 = heights[st.pop()];
                        if(st.empty()){
    
    
                            maxS = Math.max(tempH2 * i,maxS);
                            break;
                        }else {
    
    

                        }
                        maxS = Math.max(maxS, (i - st.peek() - 1) * tempH2);


                }
                st.push(i);
            }
        }
        //添加完毕,依次出栈
        if(!st.empty()){
    
    
            int tempH = heights[st.peek()];
            int tempI = st.pop();
            if (st.empty()){
    
    
                maxS = Math.max(maxS, tempH);
                return maxS;
            }else {
    
    
                maxS = Math.max(maxS, tempH * (tempI - st.peek()));
            }

            while(!st.empty()){
    
    
                int tempH2 = heights[st.pop()];
                if(st.empty()){
    
    
                    maxS = Math.max(tempH2 * (tempI + 1),maxS);
                    break;
                }
                maxS = Math.max(maxS, (tempI - st.peek()) * tempH2);
            }
        }
        return maxS;

    }
}

At the same time, there is also a tricky approach to this question. If two rectangles with a height of 0 are added at the beginning and the end, without affecting the result, the process statistics can be counted, that is, when the rightmost 0 is pushed, all the rectangles will be popped out of the stack . All rectangles will be popped out of the stack, that is, the calculation is completed.
JAVA code implementation

	 public int largestRectangleArea(int[] heights) {
    
    
        int res =0 ;
        int n = heights.length;
        int[] arr = new int[n+2];
        //复制数组,首位加0
        System.arraycopy(heights,0,arr,1,n);
        Deque<Integer> stack = new ArrayDeque<>();
        int nOfArr = arr.length;

        arr[0] = arr[nOfArr-1] = 0;
        //依次比较入栈
        for (int i = 0; i < nOfArr; i++) {
    
    
            int h = arr[i];
            while (!stack.isEmpty() && h < arr[stack.peek()]){
    
    
                int tmph = arr[stack.pop()];
                res = Math.max(res,tmph * (i - stack.peek() - 1));
            }
            stack.push(i);
        }

        return res;
    }

Guess you like

Origin blog.csdn.net/faker1234546/article/details/129241656