咱们继续,再来个最大矩形。
不同于 柱状图的最大矩形,这次计算的是一个矩阵,而矩阵是由一行一行数据组成的,就意味着其是多个相同个数的柱状图组成的,以案例为例:
## 矩阵 [0] 1 0 1 0 0 [1] 1 0 1 1 1 [2] 1 1 1 1 1 [3] 1 0 0 1 0 ## [0] 1 0 1 0 0 对应柱形 1 0 1 0 0 ## [1] 1 0 1 1 1 对应柱形 2 0 2 0 0 1 0 1 1 1 ## [2] 1 1 1 1 1 对应柱形 3 0 3 0 0 2 0 2 2 2 1 1 1 1 1 ## [3] 1 0 0 1 0 对应柱形 4 0 3 0 3 2 2 1 0 0 1 0
则我们可以遍历矩阵的每一行,计算其对应的矩形,剩下的交给求柱形的最大矩形函数中计算。
因此我们需要解决问题只有如何去计算矩阵单行对应的矩形,而上面的方式我们已经说明了如何去计算:
- 记录[0]的对应数据,第一个柱状图实现;
- 接下来到[1],使用第一个柱状图,如果本行为0则无柱状图出现,如果本行为1则可以对应之前的高度+1;
- 后续均如此
依照这个规则我们写成代码:
// 柱状图的柱形个数
auto size = matrix[0].size();
// 存储矩形 并初始化
vector<int> heights(size, 0);
// 结果
int res{0};
// 遍历一层矩形
for (const auto &row : matrix) {
// 遍历第二层矩形
for (size_t i{0}; i<size; ++i) {
// 获取矩形的高度
// 当前的指向 数字
int cur = row[i] - '0';
switch (cur) {
case 0:
heights[i] = 0;
break;
case 1:
heights[i] += 1;
break;
default:
break;
}
}
// 获取完成
// 其他操作
} 每一次第二层循环都会确定一层的柱状图,根据这个柱状图可以使用之前的思路实现最大面积计算,回忆一下前面的代码,柱状图的最大矩形:
int maxArea(vector<int>& heights) {
// 获取柱形个数
auto size = heights.size();
// 存储边界
stack<int> stk;
// 结果
int res{0};
for (size_t i{0}; i<size; ++i) {
int cur = heights[i];
// 若栈中无元素
if (stk.empty()) {
stk.push(i);
continue;
}
int top_i = stk.top(); // 栈顶索引
int top = heights[top_i]; // 栈顶对应元素
// 触发计算边界
while (!stk.empty() && cur < top) {
// 弹出栈顶
stk.pop();
int left = stk.empty() ? 0 : stk.top() + 1;
int right = i-1;
int width = right-left+1;
// 计算面积
int area = width*top;
// 获取最大
res = max(res, area);
// 下一个条件
top_i = stk.empty() ? 0 : stk.top();
top = heights[top_i];
}
// 完成计算
stk.push(i);
}
// 栈不空
while(!stk.empty()) {
int top_i = stk.top();
stk.pop();
int top = heights[top_i];
int left = stk.empty() ? 0 : stk.top() + 1;
int right = size-1;
int width = right - left + 1;
int area = width*top;
res = max(res, area);
}
// 计算完了
return res;
} 完成这个函数之后,就可以写入整体代码了:
class Solution {
public:
int maxArea(vector<int>& heights) {
// 获取柱形个数
auto size = heights.size();
// 存储边界
stack<int> stk;
// 结果
int res{0};
for (size_t i{0}; i<size; ++i) {
int cur = heights[i];
// 若栈中无元素
if (stk.empty()) {
stk.push(i);
continue;
}
int top_i = stk.top(); // 栈顶索引
int top = heights[top_i]; // 栈顶对应元素
// 触发计算边界
while (!stk.empty() && cur < top) {
// 弹出栈顶
stk.pop();
int left = stk.empty() ? 0 : stk.top() + 1;
int right = i-1;
int width = right-left+1;
// 计算面积
int area = width*top;
// 获取最大
res = max(res, area);
// 下一个条件
top_i = stk.empty() ? 0 : stk.top();
top = heights[top_i];
}
// 完成计算
stk.push(i);
}
// 栈不空
while(!stk.empty()) {
int top_i = stk.top();
stk.pop();
int top = heights[top_i];
int left = stk.empty() ? 0 : stk.top() + 1;
int right = size-1;
int width = right - left + 1;
int area = width*top;
res = max(res, area);
}
// 计算完了
return res;
}
int maximalRectangle(vector<vector<char>>& matrix) {
if (0 == matrix.size()) {
return 0;
}
// 柱状图的柱形个数
auto size = matrix[0].size();
// 存储矩形 并初始化
vector<int> heights(size, 0);
// 结果
int res{0};
// 遍历一层矩形
for (const auto &row : matrix) {
// 遍历第二层矩形
for (size_t i{0}; i<size; ++i) {
// 获取矩形的高度
// 当前的指向 数字
int cur = row[i] - '0';
switch (cur) {
case 0:
heights[i] = 0;
break;
case 1:
heights[i] += 1;
break;
default:
break;
}
}
// 获取完成
// 其他操作
res = max(res, maxArea(heights));
}
return res;
}
}; 执行用时:52 ms, 在所有 C++ 提交中击败了94.39% 的用户 内存消耗:12.1 MB, 在所有 C++ 提交中击败了44.37% 的用户
还行,时间复杂度为O(M*N),即取决于矩阵的大小。不过有其他方法吗?
不过这已经是比较简便的思路了,无论如何做,都需要将矩阵遍历一遍,因此时间复杂度无法再降低了。
可以尝试将柱状图的方法融合进代码,实现代码的精简,在一些细节上可以降低些运行时间,但具体就不做了。
(还有动态规划,但本处确保使用栈)
如有错误,欢迎指正!
如有不懂,欢迎讨论!
感谢🙏🏻️观看!

京公网安备 11010502036488号