Skip to content

Commit 25c3258

Browse files
committed
feat: add solutions to lcof2 problem: No.040
No.040.Maximal Rectangle
1 parent 453aa7f commit 25c3258

File tree

4 files changed

+306
-5
lines changed

4 files changed

+306
-5
lines changed

lcof2/剑指 Offer II 040. 矩阵中最大的矩形/README.md

+180-5
Original file line numberDiff line numberDiff line change
@@ -69,10 +69,9 @@
6969

7070
**方法一:单调栈**
7171

72-
- 首先在柱状图中求最大矩形面积可以通过单调栈,维护每一列的左边第一个比它小的位置 $L$,和右边第一个比它小的位置 $R$,就能得到以这一列为高的最大矩形面积为 $(R-L-1)*h$。
73-
- 考虑每一行作为底边的柱状图中,能够得到的最大的矩形面积。再对每一行的最大面积取 $max$ 就是最终的答案。
74-
- 柱状图中每一列的高可以通过类似前缀和的方式去维护。
75-
- 假设矩阵大小为 $n*m$,那么时间复杂为 $O(nm)$,空间复杂度为 $O(m)$。
72+
把每一行视为柱状图的底部,对每一行求柱状图的最大面积即可。
73+
74+
时间复杂度 $O(mn)$,其中 $m$ 表示 $matrix$ 的行数,$n$ 表示 $matrix$ 的列数。
7675

7776
<!-- tabs:start -->
7877

@@ -81,19 +80,97 @@
8180
<!-- 这里可写当前语言的特殊实现逻辑 -->
8281

8382
```python
84-
83+
class Solution:
84+
def maximalRectangle(self, matrix: List[List[str]]) -> int:
85+
if not matrix:
86+
return 0
87+
heights = [0] * len(matrix[0])
88+
ans = 0
89+
for row in matrix:
90+
for j, v in enumerate(row):
91+
if v == "1":
92+
heights[j] += 1
93+
else:
94+
heights[j] = 0
95+
ans = max(ans, self.largestRectangleArea(heights))
96+
return ans
97+
98+
def largestRectangleArea(self, heights: List[int]) -> int:
99+
n = len(heights)
100+
stk = []
101+
left = [-1] * n
102+
right = [n] * n
103+
for i, h in enumerate(heights):
104+
while stk and heights[stk[-1]] >= h:
105+
stk.pop()
106+
if stk:
107+
left[i] = stk[-1]
108+
stk.append(i)
109+
stk = []
110+
for i in range(n - 1, -1, -1):
111+
h = heights[i]
112+
while stk and heights[stk[-1]] >= h:
113+
stk.pop()
114+
if stk:
115+
right[i] = stk[-1]
116+
stk.append(i)
117+
return max(h * (right[i] - left[i] - 1) for i, h in enumerate(heights))
85118
```
86119

87120
### **Java**
88121

89122
<!-- 这里可写当前语言的特殊实现逻辑 -->
90123

91124
```java
125+
class Solution {
126+
public int maximalRectangle(String[] matrix) {
127+
if (matrix == null || matrix.length == 0) {
128+
return 0;
129+
}
130+
int n = matrix[0].length();
131+
int[] heights = new int[n];
132+
int ans = 0;
133+
for (var row : matrix) {
134+
for (int j = 0; j < n; ++j) {
135+
if (row.charAt(j) == '1') {
136+
heights[j] += 1;
137+
} else {
138+
heights[j] = 0;
139+
}
140+
}
141+
ans = Math.max(ans, largestRectangleArea(heights));
142+
}
143+
return ans;
144+
}
92145

146+
private int largestRectangleArea(int[] heights) {
147+
int res = 0, n = heights.length;
148+
Deque<Integer> stk = new ArrayDeque<>();
149+
int[] left = new int[n];
150+
int[] right = new int[n];
151+
Arrays.fill(right, n);
152+
for (int i = 0; i < n; ++i) {
153+
while (!stk.isEmpty() && heights[stk.peek()] >= heights[i]) {
154+
right[stk.pop()] = i;
155+
}
156+
left[i] = stk.isEmpty() ? -1 : stk.peek();
157+
stk.push(i);
158+
}
159+
for (int i = 0; i < n; ++i) {
160+
res = Math.max(res, heights[i] * (right[i] - left[i] - 1));
161+
}
162+
return res;
163+
}
164+
}
93165
```
94166

95167
### **C++**
96168

169+
- 首先在柱状图中求最大矩形面积可以通过单调栈,维护每一列的左边第一个比它小的位置 $L$,和右边第一个比它小的位置 $R$,就能得到以这一列为高的最大矩形面积为 $(R-L-1)*h$。
170+
- 考虑每一行作为底边的柱状图中,能够得到的最大的矩形面积。再对每一行的最大面积取 $max$ 就是最终的答案。
171+
- 柱状图中每一列的高可以通过类似前缀和的方式去维护。
172+
- 假设矩阵大小为 $n*m$,那么时间复杂为 $O(nm)$,空间复杂度为 $O(m)$。
173+
97174
```cpp
98175
class Solution {
99176
public:
@@ -130,6 +207,104 @@ public:
130207
};
131208
```
132209
210+
```cpp
211+
class Solution {
212+
public:
213+
int maximalRectangle(vector<string>& matrix) {
214+
if (matrix.empty()) return 0;
215+
int n = matrix[0].size();
216+
vector<int> heights(n);
217+
int ans = 0;
218+
for (auto& row : matrix)
219+
{
220+
for (int j = 0; j < n; ++j)
221+
{
222+
if (row[j] == '1') ++heights[j];
223+
else heights[j] = 0;
224+
}
225+
ans = max(ans, largestRectangleArea(heights));
226+
}
227+
return ans;
228+
}
229+
230+
int largestRectangleArea(vector<int>& heights) {
231+
int res = 0, n = heights.size();
232+
stack<int> stk;
233+
vector<int> left(n, -1);
234+
vector<int> right(n, n);
235+
for (int i = 0; i < n; ++i)
236+
{
237+
while (!stk.empty() && heights[stk.top()] >= heights[i])
238+
{
239+
right[stk.top()] = i;
240+
stk.pop();
241+
}
242+
if (!stk.empty()) left[i] = stk.top();
243+
stk.push(i);
244+
}
245+
for (int i = 0; i < n; ++i)
246+
res = max(res, heights[i] * (right[i] - left[i] - 1));
247+
return res;
248+
}
249+
};
250+
```
251+
252+
### **Go**
253+
254+
```go
255+
func maximalRectangle(matrix []string) int {
256+
if len(matrix) == 0 {
257+
return 0
258+
}
259+
n := len(matrix[0])
260+
heights := make([]int, n)
261+
ans := 0
262+
for _, row := range matrix {
263+
for j, v := range row {
264+
if v == '1' {
265+
heights[j]++
266+
} else {
267+
heights[j] = 0
268+
}
269+
}
270+
ans = max(ans, largestRectangleArea(heights))
271+
}
272+
return ans
273+
}
274+
275+
func largestRectangleArea(heights []int) int {
276+
res, n := 0, len(heights)
277+
var stk []int
278+
left, right := make([]int, n), make([]int, n)
279+
for i := range right {
280+
right[i] = n
281+
}
282+
for i, h := range heights {
283+
for len(stk) > 0 && heights[stk[len(stk)-1]] >= h {
284+
right[stk[len(stk)-1]] = i
285+
stk = stk[:len(stk)-1]
286+
}
287+
if len(stk) > 0 {
288+
left[i] = stk[len(stk)-1]
289+
} else {
290+
left[i] = -1
291+
}
292+
stk = append(stk, i)
293+
}
294+
for i, h := range heights {
295+
res = max(res, h*(right[i]-left[i]-1))
296+
}
297+
return res
298+
}
299+
300+
func max(a, b int) int {
301+
if a > b {
302+
return a
303+
}
304+
return b
305+
}
306+
```
307+
133308
### **...**
134309

135310
```
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
func maximalRectangle(matrix []string) int {
2+
if len(matrix) == 0 {
3+
return 0
4+
}
5+
n := len(matrix[0])
6+
heights := make([]int, n)
7+
ans := 0
8+
for _, row := range matrix {
9+
for j, v := range row {
10+
if v == '1' {
11+
heights[j]++
12+
} else {
13+
heights[j] = 0
14+
}
15+
}
16+
ans = max(ans, largestRectangleArea(heights))
17+
}
18+
return ans
19+
}
20+
21+
func largestRectangleArea(heights []int) int {
22+
res, n := 0, len(heights)
23+
var stk []int
24+
left, right := make([]int, n), make([]int, n)
25+
for i := range right {
26+
right[i] = n
27+
}
28+
for i, h := range heights {
29+
for len(stk) > 0 && heights[stk[len(stk)-1]] >= h {
30+
right[stk[len(stk)-1]] = i
31+
stk = stk[:len(stk)-1]
32+
}
33+
if len(stk) > 0 {
34+
left[i] = stk[len(stk)-1]
35+
} else {
36+
left[i] = -1
37+
}
38+
stk = append(stk, i)
39+
}
40+
for i, h := range heights {
41+
res = max(res, h*(right[i]-left[i]-1))
42+
}
43+
return res
44+
}
45+
46+
func max(a, b int) int {
47+
if a > b {
48+
return a
49+
}
50+
return b
51+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
class Solution {
2+
public int maximalRectangle(String[] matrix) {
3+
if (matrix == null || matrix.length == 0) {
4+
return 0;
5+
}
6+
int n = matrix[0].length();
7+
int[] heights = new int[n];
8+
int ans = 0;
9+
for (var row : matrix) {
10+
for (int j = 0; j < n; ++j) {
11+
if (row.charAt(j) == '1') {
12+
heights[j] += 1;
13+
} else {
14+
heights[j] = 0;
15+
}
16+
}
17+
ans = Math.max(ans, largestRectangleArea(heights));
18+
}
19+
return ans;
20+
}
21+
22+
private int largestRectangleArea(int[] heights) {
23+
int res = 0, n = heights.length;
24+
Deque<Integer> stk = new ArrayDeque<>();
25+
int[] left = new int[n];
26+
int[] right = new int[n];
27+
Arrays.fill(right, n);
28+
for (int i = 0; i < n; ++i) {
29+
while (!stk.isEmpty() && heights[stk.peek()] >= heights[i]) {
30+
right[stk.pop()] = i;
31+
}
32+
left[i] = stk.isEmpty() ? -1 : stk.peek();
33+
stk.push(i);
34+
}
35+
for (int i = 0; i < n; ++i) {
36+
res = Math.max(res, heights[i] * (right[i] - left[i] - 1));
37+
}
38+
return res;
39+
}
40+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
class Solution:
2+
def maximalRectangle(self, matrix: List[List[str]]) -> int:
3+
if not matrix:
4+
return 0
5+
heights = [0] * len(matrix[0])
6+
ans = 0
7+
for row in matrix:
8+
for j, v in enumerate(row):
9+
if v == "1":
10+
heights[j] += 1
11+
else:
12+
heights[j] = 0
13+
ans = max(ans, self.largestRectangleArea(heights))
14+
return ans
15+
16+
def largestRectangleArea(self, heights: List[int]) -> int:
17+
n = len(heights)
18+
stk = []
19+
left = [-1] * n
20+
right = [n] * n
21+
for i, h in enumerate(heights):
22+
while stk and heights[stk[-1]] >= h:
23+
stk.pop()
24+
if stk:
25+
left[i] = stk[-1]
26+
stk.append(i)
27+
stk = []
28+
for i in range(n - 1, -1, -1):
29+
h = heights[i]
30+
while stk and heights[stk[-1]] >= h:
31+
stk.pop()
32+
if stk:
33+
right[i] = stk[-1]
34+
stk.append(i)
35+
return max(h * (right[i] - left[i] - 1) for i, h in enumerate(heights))

0 commit comments

Comments
 (0)