leetcode brushing problem set: monotone stack (python code)

Preface Sui Sui Nian: In the autumn recruiting questions, sort out some series of question types.

classic examples

42. Catching rainwater

leetcode

topic

Given n non-negative integers representing the height map of each column with a width of 1, calculate how much rainwater can be received by the columns arranged in this way after it rains.

Example 1:

输入:height = [0,1,0,2,1,0,1,3,2,1,2,1]
输出:6
解释:上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图,在这种情况下,可以接 6 个单位的雨水(蓝色部分表示雨水)。 

Example 2:

输入:height = [4,2,0,3,2,5]
输出:9

hint:

  • n = = h e i g h t . l e n g t h n == height.length n==height.length
  • 1 < = n < = 2 ∗ 1 0 4 1 <= n <= 2 * 10^4 1<=n<=2104
  • 0 < = h e i g h t [ i ] < = 1 0 5 0 <= height[i] <= 10^5 0<=height[i]<=105

train of thought

Maintain a monotonic stack, and store the subscript ii in the stacki , the height corresponding to the subscriptheight [ i ] height[i]h e i g h t [ i ] increases from the top of the stack to the bottom of the stack, that is,the height of the element at the top of the stack [ − 1 ] height[-1]h e i g h t [ 1 ] is the smallest

By situation:

  • If the element to be pushed into the stack >= the top of the stack: push into the stack
  • If the element to be stacked < the top of the stack: Calculate the area
    • Receive water: top of the stack (middle) + second element of the stack (left) + to be pushed into the stack
    • Please add a picture description
    • Please add a picture description
    • Please add a picture description
    • Please add a picture description

the code

class Solution(object):
    def trap(self, height):
        """
        :type height: List[int]
        :rtype: int
        """
        stack = []
        ans = 0

        for i in range(len(height)):
            # 计算面积
            while len(stack)>0 and height[i]>height[stack[-1]]:
                mid = stack[-1]
                stack.pop()
                if len(stack)>0:
                    h = min(height[i], height[stack[-1]])-height[mid]
                    w = i - stack[-1] - 1
                    ans += h*w

            stack.append(i)
        
        return ans

84. Largest Rectangle in Histogram

leetcode

topic

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.

Example 1:

输入:heights = [2,1,5,6,2,3]
输出:10
解释:最大的矩形为图中红色区域,面积为 10

Example 2:

输入:heights = [2,4]
输出:4

hint:

  • 1 < = h e i g h t s . l e n g t h < = 1 0 5 1 <= heights.length <=10^5 1<=heights.length<=105
  • 0 < = h e i g h t s [ i ] < = 1 0 4 0 <= heights[i] <= 10^4 0<=heights[i]<=104

train of thought

Monotonic stack + sentinel mechanism
to store subscripts

Take the example array [2, 1, 5, 6, 2, 3]as an example:

1. The height of the column seen at the beginning is 2. At this time, 2the rectangle with the largest area with this height as the height cannot be determined. We need to continue to traverse to the right, as shown in the figure below.

2. Then you see a column with a height of 1. At this time, the maximum area of ​​the rectangle with this column as the height is still unknown. However, the rectangle with the maximum area whose height is 2 can be determined, because this 1 is smaller than 2, because this 1 is stuck here, and 2 can no longer expand to the right, as shown in the figure below.

Let's calculate that the area of ​​the largest rectangle with height 2 is 2. In fact, at this time, the idea of ​​solving this problem has actually been slowly opened. If the height of a column has been determined, we can ignore it and represent it with a dashed box, as shown in the figure below.

3. After traversing to the column with a height of 5, the maximum area of ​​the rectangle with the currently seen column as the height is also unknown, because we still need to look at the height of the right side. So is there any definite column shape on its left and right sides? No, this is because 5 is bigger than 1, we see that 6 will appear immediately behind, whether it is the column of 1 or the column of 5, it can still expand to the right;


4. Next, it traverses to 6the column with a height of . Similarly, the maximum rectangular area with the height of the column 1, 5, 6is still not determined;

5. Next, traverses to 2the column with a height of .

I found a very amazing thing, the width of the area of ​​the largest rectangle corresponding to the column with a height of 6 can be determined, it is the distance between the column with a height of 5 and the column with a height of 2, its height is 6, and its width is 1.

Set the bars that can be determined as dashed lines.

Next, 5the width of the rectangle with the largest area corresponding to the column can also be determined, which is the distance between the two columns with a height of 1and a height of ; after it is determined, we will mark it as a dotted line. 6. Finally traverse to the last column, that is, the column with a height of 3. Next we have to consider the height of the columns that are still in the stack in turn. It is the same as the previous method, except that there is no column smaller than it on the right at this time, assuming that there is a column with a subscript len ​​(here equal to 6) and a height of 0 on the far right.2






7. The subscript is 5, that is, a column with a height of 3, the subscript on the left is 4, and the subscript on the right is 6, so the width is 6 - 4 - 1 = 1 (both sides are not counted, only the distance in the middle, so subtract 1); after the calculation, mark it as a dotted line.

8. For a column with a subscript of 4 and a height of 2, the subscript on the left is 1 and the subscript on the right is 6, so the width is 6 - 1 - 1 = 4; after the calculation, mark it as a dotted line.

9. Finally, look at the rectangle whose subscript is 1 and height is 1. In fact, there are no elements on its left and right sides. It is the lowest height column in the entire column array. Calculate its width, which is the length of the entire column array.

Two special cases need to be considered:

  1. When the stack is popped, the stack is empty;
  2. After the traversal is complete, there are still elements in the stack;

For this reason, we can add two columns with a height of 0 (or 0.5, as long as it is strictly smaller than 1) at both ends of the input array, which can avoid the above two classification discussions.

These two columns standing on both sides have a very vivid term called Sentinel .

With these two bars:

  • Since the column on the left (the first column) must be smaller than any element in the input array, it will definitely not pop out of the stack, so the stack must not be empty;

  • The bar on the right (the second bar) is precisely because it must be smaller than any element in the input array, it will pop all the elements in the input array (except the first sentinel element).

the code

class Solution(object):
    def largestRectangleArea(self, heights):
        """
        :type heights: List[int]
        :rtype: int
        """
        ans = 0
        heights = [0] + heights + [0]          # 添加哨兵
        stack = [0]
        for i in range(1, len(heights)):       # 从 1 开始
            while heights[i] < heights[stack[-1]]:
                h = heights[stack.pop()]        # 要先pop出来,利用左边的下标
                w = i - stack[-1] - 1
                ans = max(ans, h*w)
                
            stack.append(i)
        
        return ans

85. Largest Rectangle

leetcode

topic

Given a 2D binary matrix of size containing only 0and , find the largest rectangle containing only and return its area.1rows x cols1

Example 1:

输入:matrix = [["1","0","1","0","0"],["1","0","1","1","1"],["1","1","1","1","1"],["1","0","0","1","0"]]
输出:6
解释:最大矩形如上图所示。

Example 2:

输入:matrix = []
输出:0

Example 3:

输入:matrix = [["0"]]
输出:0

Example 4:

输入:matrix = [["1"]]
输出:1

Example 5:

输入:matrix = [["0","0"]]
输出:0
 

hint:

  • r o w s = = m a t r i x . l e n g t h rows == matrix.length rows==matrix.length
  • c o l s = = m a t r i x [ 0 ] . l e n g t h cols == matrix[0].length cols==matrix[0].length
  • 1 < = r o w , c o l s < = 200 1 <= row, cols <= 200 1<=row,cols<=200
  • matrix [ i ] [ j ] is ' 0 ' or ' 1 ' matrix[i][j] is '0' or '1'ma t r i x [ i ] [ j ] is0' or1

train of thought

Following the idea of ​​the previous question, turn each column into a histogram according to the vertical direction, and calculate the area of ​​the rectangle with the lower right corner

the code

class Solution(object):
    def maximalRectangle(self, matrix):
        """
        :type matrix: List[List[str]]
        :rtype: int
        """
        r, c = len(matrix), len(matrix[0])
        left = [[0]*c for _ in range(r+2)]      # 引入哨兵

        for i in range(r):
            for j in range(c):
                if matrix[i][j]=='1':
                    if j==0:
                        left[i+1][j] = 1
                    else:
                        left[i+1][j] = left[i+1][j-1] + 1
                else:
                    left[i+1][j] = 0
                    
        ans = 0
        for j in range(c):
            stack = [0]
            for i in range(1, r+2):
                while left[stack[-1]][j] > left[i][j]:
                    h = left[stack.pop()][j]
                    w = i - stack[-1] - 1
                    ans = max(ans, h*w)
                stack.append(i)
            
        return ans

References

  1. Brute force solution, stack (monotonic stack, sentinel trick)
  2. The official problem solution of the largest rectangle

Guess you like

Origin blog.csdn.net/iteapoy/article/details/126898939