Preface Sui Sui Nian: In the autumn recruiting questions, sort out some series of question types.
Article Directory
classic examples
42. Catching rainwater
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<=2∗104
- 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
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
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, 2
the 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 6
the column with a height of . Similarly, the maximum rectangular area with the height of the column 1
, 5
, 6
is still not determined;
5. Next, traverses to 2
the 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, 5
the 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 1
and 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:
- When the stack is popped, the stack is empty;
- 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
topic
Given a 2D binary matrix of size containing only 0
and , find the largest rectangle containing only and return its area.1
rows x cols
1
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 ] is′0' or′1′
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