当前位置: 首页 > news >正文

LeetCode 85:最大矩形

LeetCode 85:最大矩形

在这里插入图片描述

问题本质与核心挑战

给定仅含 01 的二维矩阵,需找到全由 1 组成的最大矩形面积。核心挑战:

  • 直接枚举所有矩形(O(n²m²))效率极低;
  • 需通过 “逐行构建柱状图 + 单调栈求最大面积” 优化,将复杂度降为 O(rows×cols)

核心思路:二维 → 一维的转化

1. 柱状图的构建

对矩阵的每一行,计算以该行作为底边的“柱状图高度”:

  • 若当前单元格为 1,则高度为上方连续 1 的个数 + 1(继承上一行的高度);
  • 若当前单元格为 0,则高度重置为 0(无法形成垂直连续的 1)。
2. 复用柱状图最大面积算法(LeetCode 84题)

对每一行构建的柱状图,使用 单调栈 快速计算其最大矩形面积(时间复杂度 O(cols)),最终取所有行的最大值。

算法步骤详解(以示例 matrix = [[1,0,1,0,0],[1,0,1,1,1],[1,1,1,1,1],[1,0,0,1,0]] 为例)

步骤 1:初始化变量与高度数组
int rows = matrix.length;   // 行数(4)
int cols = matrix[0].length; // 列数(5)
int[] height = new int[cols]; // 记录当前行的柱状图高度
int maxArea = 0; // 全局最大面积
步骤 2:逐行构建柱状图,计算最大面积

遍历每一行,更新 height 数组,并调用 largestRectangleArea 计算当前行的最大面积:

for (int i = 0; i < rows; i++) {// 更新当前行的高度数组for (int j = 0; j < cols; j++) {height[j] = (matrix[i][j] == '1') ? height[j] + 1 : 0;}// 计算当前柱状图的最大面积,更新全局最大值maxArea = Math.max(maxArea, largestRectangleArea(height));
}

示例演示(行2的 height 构建)

  • 行2的 matrix["1","1","1","1","1"]
    • j=0matrix[2][0]='1'height[0] = height[0](2) + 1 = 3
    • j=1matrix[2][1]='1'height[1] = height[1](0) + 1 = 1
    • 最终 height = [3,1,3,2,2](对应柱状图高度)。
步骤 3:单调栈计算柱状图最大面积(复用LeetCode 84题逻辑)
private int largestRectangleArea(int[] heights) {Stack<Integer> stack = new Stack<>(); // 存储索引,保持高度递增int max = 0;int n = heights.length;for (int i = 0; i < n; i++) {// 当前高度 < 栈顶高度 → 弹出栈顶,计算面积while (!stack.isEmpty() && heights[i] < heights[stack.peek()]) {int top = stack.pop();int h = heights[top];int left = stack.isEmpty() ? -1 : stack.peek(); // 左边界int right = i; // 右边界max = Math.max(max, h * (right - left - 1));}stack.push(i); // 当前索引入栈}// 处理栈中剩余元素(右边界为n)while (!stack.isEmpty()) {int top = stack.pop();int h = heights[top];int left = stack.isEmpty() ? -1 : stack.peek();int right = n;max = Math.max(max, h * (right - left - 1));}return max;
}

示例演示(行2的 height = [3,1,3,2,2]

步骤栈状态操作计算的面积局部max
i=0(height=3)[0]压入0-0
i=1(height=1)[1]弹出0 → 面积 3×(1-(-1)-1)=333
i=2(height=3)[1,2]压入2-3
i=3(height=2)[1,3]弹出2 → 面积 3×(3-1-1)=3;弹出1 → 面积 1×(3-(-1)-1)=33,33
i=4(height=2)[3,4]压入4-3
遍历结束,处理栈[]弹出4 → 面积 2×(5-3-1)=2;弹出3 → 面积 2×(5-1-1)=62,66

完整代码(Java)

import java.util.Stack;class Solution {public int maximalRectangle(char[][] matrix) {if (matrix == null || matrix.length == 0) {return 0;}int rows = matrix.length;int cols = matrix[0].length;int[] height = new int[cols]; // 记录当前行的柱状图高度int maxArea = 0;for (int i = 0; i < rows; i++) {// 逐列更新高度:当前为'1'则累加,否则置0for (int j = 0; j < cols; j++) {height[j] = (matrix[i][j] == '1') ? height[j] + 1 : 0;}// 计算当前行的最大矩形面积,更新全局最大值maxArea = Math.max(maxArea, largestRectangleArea(height));}return maxArea;}// 复用LeetCode 84题的单调栈解法,计算柱状图的最大矩形面积private int largestRectangleArea(int[] heights) {Stack<Integer> stack = new Stack<>();int maxArea = 0;int n = heights.length;for (int i = 0; i < n; i++) {// 维护单调递增栈:当前高度 < 栈顶高度时,弹出栈顶计算面积while (!stack.isEmpty() && heights[i] < heights[stack.peek()]) {int topIndex = stack.pop();int h = heights[topIndex];// 左边界:栈空则为-1,否则为新栈顶int left = stack.isEmpty() ? -1 : stack.peek();// 右边界:当前索引iint right = i;int width = right - left - 1;maxArea = Math.max(maxArea, h * width);}stack.push(i); // 当前索引入栈}// 处理栈中剩余元素(右边界为n)while (!stack.isEmpty()) {int topIndex = stack.pop();int h = heights[topIndex];int left = stack.isEmpty() ? -1 : stack.peek();int right = n;int width = right - left - 1;maxArea = Math.max(maxArea, h * width);}return maxArea;}
}

关键逻辑解析

1. 柱状图的构建逻辑
  • 若当前单元格为 1,高度继承自上一行同列的高度(height[j] += 1),形成垂直连续的 1
  • 若为 0,高度重置为 0(垂直连续中断)。
2. 单调栈的作用
  • 维护递增的高度索引,确保每次弹出栈顶时,其左右边界是第一个比它矮的柱子,从而快速计算以该高度为高的矩形面积。
3. 时间复杂度
  • 每行处理:O(cols)(更新高度 + 单调栈操作,每个元素入栈、出栈各一次);
  • 总复杂度:O(rows×cols),可处理题目中 rows, cols ≤ 200 的规模。

该方法通过二维转一维的巧妙转化,将复杂的二维矩形问题拆解为多个一维柱状图问题,再利用单调栈高效求解,体现了算法优化中降维思想经典模板复用的精髓。

http://www.lryc.cn/news/606473.html

相关文章:

  • Shader开发(五)什么是渲染管线
  • Flutter兼容的iOS的最低版本号
  • 链特异性文库是什么?为什么它在转录组测序中越来越重要?
  • 【普中STM32精灵开发攻略】--第 2 章 开发板功能及使用介绍
  • 浅谈“压敏电阻”
  • 基于单片机智能油烟机设计/厨房排烟系统设计
  • 开发避坑短篇(12):达梦数据库TIMESTAMP字段日期区间查询实现方案
  • 快速搭建Java服务指南
  • 网站技术攻坚与Bug围剿手记
  • 环境配置·mmsegmentation和mmcv的安装
  • 【11】大恒相机SDK C++开发 ——原图像数据IFrameData内存中上下颠倒,怎么裁剪ROI 实时显示在pictureBox中
  • PostGIS面试题及详细答案120道之 (061-070 )
  • sqli-labs靶场Less24
  • 网络基础——路由控制
  • 逻辑回归算法基础介绍,简单的二分类三分类实例
  • 异常检测:算法分类及经典模型概览
  • npm 设置国内镜像源
  • 正点原子 ATK-BLE04 、ATK-BLE05 蓝牙模块学习使用
  • Motif技术团队:利用行为序列预测模型进行因果推断的案例(二)
  • 嵌入式第十六课!!!结构体与共用体
  • 【Python修仙编程】(二) Python3灵源初探(9)
  • 7.31IO进程线程——标准IO函数
  • 在window中安装swow体验php协程
  • 【07】大恒相机SDK C#开发 —— 相机IO触发采集与信号输出
  • 2025年IntelliJ IDEA最新下载、安装教程,附详细图文
  • 最新PS 2025安装包下载与安装教程(Adobe Photoshop 2025 )
  • Linux731 shell工具;[]字符
  • imx6ull-驱动开发篇5——新字符设备驱动实验
  • 【MATLAB】(三)数据类型与运算符
  • 在MySQL中DECIMAL 类型的小数位数(Scale)如何影响分组查询?