【算法】单调栈题单——矩阵系列⭐

文章目录

  • 题目列表
    • 84. 柱状图中最大的矩形(单调栈找左右两边第一个更低的位置)
    • 85. 最大矩形⭐⭐⭐⭐⭐
      • 解法1——使用柱状图的优化暴力方法
      • 解法2——单调栈 :归因到 84. 柱状图中最大的矩形 🐂
    • 1504. 统计全 1 子矩形⭐
  • 相关链接

题目列表

84. 柱状图中最大的矩形(单调栈找左右两边第一个更低的位置)

https://leetcode.cn/problems/largest-rectangle-in-histogram/description/

在这里插入图片描述

提示:
1 <= heights.length <=10^5
0 <= heights[i] <= 10^4

以 heights[i] 为高度的矩形,它的宽是* (r[i] - l[i] - 1);
其中 r[i] 和 l[i] 为左右两边第一个更低的位置。

class Solution {
    public int largestRectangleArea(int[] heights) {
        int n = heights.length;
        // 记录左右第一个比它小的下标
        int[] l = new int[n], r = new int[n];
        Arrays.fill(l, -1);     // 左边第一个大于heights[i]
        Arrays.fill(r, n);      // 右边第一个小于等于heights[i]
        Deque<Integer> stk = new ArrayDeque<>();
        for (int i = 0; i < n; ++i) {
            while (!stk.isEmpty() && heights[i] <= heights[stk.peek()]) {
                r[stk.pop()] = i;
            }
            if (!stk.isEmpty()) l[i] = stk.peek();
            stk.push(i);
        }
        int ans = 0;
        for (int i = 0; i < n; ++i) {
            int s = heights[i] * (r[i] - l[i] - 1);
            if (s > ans) ans = s;
        }
        return ans;
    }
}

从具体结果来看,r[i] 表示的是小于等于的而不是小于的,这看起来会出错但其实并不会。
原因在于,如果h[i]和h[j]是相同的高度,那么r[i]=j这是错误的,但是r[j]可以得出正确的答案。
具体看下面的例子:
image.png

85. 最大矩形⭐⭐⭐⭐⭐

https://leetcode.cn/problems/maximal-rectangle/description/

在这里插入图片描述

提示:
rows == matrix.length
cols == matrix[0].length
1 <= row, cols <= 200
matrix[i][j] 为 '0' 或 '1'

解法1——使用柱状图的优化暴力方法

https://leetcode.cn/problems/maximal-rectangle/solutions/535672/zui-da-ju-xing-by-leetcode-solution-bjlu/

在这里插入图片描述
在这里插入图片描述


总结一下思路:

  1. 预处理出 left[i][j],是每个点作为右下角时,它的左边包括多少连续的1。
  2. 枚举每个点作为右下角,计算其最大面积。随着高度的变大,宽度会随之减小。
class Solution {
    public int maximalRectangle(char[][] matrix) {
        int m = matrix.length, n = matrix[0].length;
        // 构造 left 数组
        int[][] left = new int[m][n];
        for (int i = 0; i < m; ++i) {
            if (matrix[i][0] == '1') left[i][0] = 1;
            for (int j = 1; j < n; ++j) {
                if (matrix[i][j] == '1') {
                    left[i][j] = left[i][j - 1] + 1;
                }
            }
        }

        int ans = 0;
        // 枚举每个点(i,j)作为右下角
        for (int i = 0; i < m; ++i) {
            for (int j = 0; j < n; ++j) {
                int width = left[i][j], area = width * 1;
                // 尝试扩展高度
                for (int k = i - 1; k >= 0; --k) {
                    width = Math.min(width, left[k][j]);
                    area = Math.max(area, width * (i - k + 1));
                }
                ans = Math.max(ans, area);
            }
        }
        return ans;
    }
}

解法2——单调栈 :归因到 84. 柱状图中最大的矩形 🐂

解法1 需要枚举每个点,对于每个点又有 m 的复杂度,所以时间复杂度是 O ( m 2 ∗ n ) O(m^2*n) O(m2n)

可以优化成求解每一行 m,对于每一行,相当于 84. 柱状图中最大的矩形 的时间复杂度,总的复杂度是 O ( m ∗ n ) O(m*n) O(mn)

在这里插入图片描述

class Solution {
    public int maximalRectangle(char[][] matrix) {
        int m = matrix.length, n = matrix[0].length;
        int[] h = new int[n];
        int[] l = new int[n], r = new int[n];
        int ans = 0;
        for (int i = 0; i < m; ++i) {
            // 处理以第 i 行为底的矩形
            for (int j = 0; j < n; ++j) {
                if (matrix[i][j] == '1') h[j]++;
                else h[j] = 0;
            }
            // 利用单调栈求解
            Deque<Integer> stk = new ArrayDeque<>();
            Arrays.fill(l, -1);
            Arrays.fill(r, n);
            for (int j = 0; j < n; ++j) {
                while (!stk.isEmpty() && h[j] < h[stk.peek()]) {
                    r[stk.pop()] = j;
                }
                if (!stk.isEmpty()) l[j] = stk.peek();
                stk.push(j);
            }
            int area = 0;
            for (int j = 0; j < n; ++j) {
                area = Math.max(area, h[j] * (r[j] - l[j] - 1));
            }
            if (area > ans) ans = area;
        }
        return ans;
    }
}

1504. 统计全 1 子矩形⭐

https://leetcode.cn/problems/count-submatrices-with-all-ones/description/

在这里插入图片描述

提示:
1 <= m, n <= 150
mat[i][j] 仅包含 0 或 1

解法1——枚举 O ( m 2 ∗ n ) O(m^2*n) O(m2n)

class Solution {
    public int numSubmat(int[][] mat) {
        int m = mat.length, n = mat[0].length, ans = 0;
        int[][] left = new int[m + 1][n + 1];
        for (int i = 1; i <= m; ++i) {
            for (int j = 1; j <= n; ++j) {
                if (mat[i - 1][j - 1] == 1) {
                    left[i][j] = left[i][j - 1] + 1;
                }

                int w = left[i][j];
                for (int k = i; k >= 1 && w > 0; --k) {
                    w = Math.min(w, left[k][j]);
                    ans += w;	// 每个高度有w个宽度可选
                }
            }
        }
        return ans;
    }
}

解法2——单调栈优化⭐⭐⭐⭐⭐(比较难理解,细细品味)

配合官解食用,https://leetcode.cn/problems/count-submatrices-with-all-ones/solutions/336410/tong-ji-quan-1-zi-ju-xing-by-leetcode-solution/

在这里插入图片描述
在这里插入图片描述

为了复用上面的结果,需要用单调栈维护一个单调非递减的序列,只有这样才能满足:该层的 sum 是上层的 sum + 该层的 w
否则,应该去除上层的额外宽度 w,同时保留其去除额外宽度之后的高度 h,加入当前层,再送入栈中。

class Solution {
    public int numSubmat(int[][] mat) {
        int m = mat.length, n = mat[0].length, ans = 0;
        int[][] left = new int[m + 1][n + 1];
        for (int i = 1; i <= m; ++i) {
            for (int j = 1; j <= n; ++j) {
                if (mat[i - 1][j - 1] == 1) {
                    left[i][j] = left[i][j - 1] + 1;
                }
            }
        }
        // 枚举每一列
        for (int j = 0; j < n; ++j) {
            Deque<int[]> stk = new ArrayDeque<>();  // 记录元素是[left[][], height]
            // 从上到下枚举每一行
            for (int i = 0, sum = 0; i < m; ++i) {
                int height = 1;                     // 初始高度为1
                // 维护宽度单调递增的单调队列
                while (!stk.isEmpty() && stk.peek()[0] > left[i + 1][j + 1]) {
                    // 去除无效的额外宽度
                    sum -= stk.peek()[1] * (stk.peek()[0] - left[i + 1][j + 1]);
                    height += stk.pop()[1];         // 继承移除的高度
                }
                sum += left[i + 1][j + 1];          // 矩形数量加上当前层的宽度
                ans += sum;
                stk.push(new int[]{left[i + 1][j + 1], height});
            }
        }
        return ans;
    }
}

相关链接

【算法】单调栈题单(矩阵系列、字典序最小、贡献法)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/214823.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Java 不要在父类的构造方法里面调用可以被子类重写的方法

不要在父类的构造方法(代码块)里面调用可以被子类重写的方法 我们从第一天学习Java开始&#xff0c;就对Java的类初始化顺序牢记于心。但是在实际开发过程中&#xff0c;似乎很难能接触这一部分的应用。在这之前&#xff0c;我也认为它只是面试中八股文而已&#xff0c;直到最…

The Big IAM Challenge 云安全 CTF 挑战赛

The Big IAM Challenge 云安全 CTF 挑战赛 今天&#xff0c;我们来做一下有关于云安全 的CTF 挑战赛 The Big IAM Challenge,旨在让白帽子识别和利用 IAM错误配置&#xff0c;并从现实场景中学习&#xff0c;从而更好的认识和了解IAM相关的风险。比赛包括6个场景&#xff0c;每…

Zotero 安装及常用插件设置指南

Zotero 安装及常用插件设置指南 本指南旨在帮助用户安装并配置 Zotero。通过本教程&#xff0c;您将能够实现以下功能&#xff1a; 界面语言设置为中文使用颜色标签来区分不同阅读状态的文献重要文献标记显示影响因子、JCP和中科院分区翻译插件Sci-Hub 集成 安装和设置步骤…

leetCode 90.子集 II + 回溯算法 + 图解 + 笔记

给你一个整数数组 nums &#xff0c;其中可能包含重复元素&#xff0c;请你返回该数组所有可能的子集&#xff08;幂集&#xff09;。 解集 不能 包含重复的子集。返回的解集中&#xff0c;子集可以按 任意顺序 排列 示例 1&#xff1a; 输入&#xff1a;nums [1,2,2] 输出…

基于CNN对彩色图像数据集CIFAR-10实现图像分类--keras框架实现

项目地址&#xff08;kaggle&#xff09;&#xff1a;基于CNN对彩色图像数据集CIFAR-10实现图像分类--keras | Kaggle 项目地址&#xff08;Colab&#xff09;&#xff1a;https://colab.research.google.com/drive/1gjzglPBfQKuhfyT3RlltCLUPgfccT_G9 导入依赖 在tensorflow…

第一百八十八回 分享三个使用TextField的细节

文章目录 1. 概念介绍2. 使用方法2.1 修改组件的填充颜色2.2 修改组件的高度2.3 给组件添加圆角3. 示例代码4. 内容总结我们在上一章回中介绍了"DropdownButton组件"相关的内容,本章回中将介绍**TextField组件的细节.**闲话休提,让我们一起Talk Flutter吧。 1. 概念…

EasyRecovery易恢复2024最新免费版电脑数据恢复软件功能介绍

EasyRecovery从&#xff08;易恢复2024&#xff09;支持恢复不同存储介质数据&#xff0c;在Windows中恢复受损和删除文件,以及能检索数据格式化或损坏卷&#xff0c;甚至还可以从初始化磁盘。同时&#xff0c;你只需要最简单的操作就可以恢复数据文件&#xff0c;如&#xff1…

YITH Product Shipping for WooCommerce商城产品配送运输插件

点击访问原文 YITH Product Shipping for WooCommerce商城产品配送运输插件 - 易服客工作室 YITH Product Shipping for WooCommerce商城产品配送运输插件根据商店的每个产品处理不同的运费&#xff0c;例如您可以为每个州、地区或城市设置不同的费用。 根据店铺的单品处理不…

搭建 ebpf 开发测试环境

0 内容说明 这部分主要讲述了如何通过官网学习ebpf&#xff0c;以及如何搭建自己的ebpf开发测试环境&#xff0c;主要是需要安装哪些工具链。 1 ebpf在线学习 ebpf官网中提供了一个快速在线学习ebpf的路径&#xff0c;在这个学习平台中一共有两项学习内容&#xff0c;一个是…

在Spring Boot中隔离@Async异步任务的线程池

在异步任务执行的时候&#xff0c;我们知道其背后都有一个线程池来执行任务&#xff0c;但是为了控制异步任务的并发不影响到应用的正常运作&#xff0c;我们需要对线程池做好相关的配置&#xff0c;以防资源过度使用。这个时候我们就考虑将线程池进行隔离了。 那么我们为啥要…

高校人员信息管理系统C++

代码&#xff1a;https://mbd.pub/o/bread/ZZeZk5lx 一、基本内容论述 1、问题描述 某高校有四类员工&#xff1a;教师、实验员、行政人员、教师兼行政人员&#xff1b;共有的信息包括&#xff1a;编号、姓名、性别、年龄等。其中&#xff0c;教师还包含的信息有&#xff1a;所…

2023年GopherChina大会-核心PPT资料下载

一、峰会简介 自 Go 语言诞生以来&#xff0c;中国便是其应用最早和最广的国家之一&#xff0c;根据 Jetbrains 在 2021 年初做的调查报告&#xff0c;总体来说目前大概有 110 万专业的开发者 选择 Go 作为其主要开发语言。就其全球分布而言, 居住在亚洲的开发者最多&#xff…

矩阵元素求和:按行、按列、所有元素np.einsum()

【小白从小学Python、C、Java】 【计算机等考500强证书考研】 【Python-数据分析】 矩阵元素求和&#xff1a; 按行、按列、所有元素 np.einsum() [太阳]选择题 下列说法正确的是&#xff1a; import numpy as np A np.array([[1, 2],[3, 4]]) print("【显示】A") p…

为何要3次握手?TCP协议的稳定性保障机制

&#x1f680; 作者主页&#xff1a; 有来技术 &#x1f525; 开源项目&#xff1a; youlai-mall &#x1f343; vue3-element-admin &#x1f343; youlai-boot &#x1f33a; 仓库主页&#xff1a; Gitee &#x1f4ab; Github &#x1f4ab; GitCode &#x1f496; 欢迎点赞…

绝地求生在steam叫什么?

绝地求生在Steam的全名是《PlayerUnknowns Battlegrounds》&#xff0c;简称为PUBG。作为一款风靡全球的多人在线游戏&#xff0c;PUBG于2017年3月23日正式上线Steam平台&#xff0c;并迅速成为一部热门游戏。 PUBG以生存竞技为核心玩法&#xff0c;玩家将被投放到一个辽阔的荒…

布林线BOLL的实战应用技巧

一、认识布林线BOLL 布林线BOLL&#xff0c;又称布林带&#xff0c;是股市中非常常用的一个技术指标。 以金斗云智投电脑版软件为例&#xff0c;任意打开一支个股&#xff0c;选择BOLL指标&#xff0c;在K线区域就可以看到上中下排列的3条线&#xff0c;这3条线就组成了布林带。…

【Three.js】创建CAD标注线

目录 &#x1f4d6;前言 &#x1f41e;创建箭头对象 &#x1f42c;创建文字 &#x1f47b;箭头两端的线段 ✈️封装方法 &#x1f4d6;前言 CAD标注线在工程和制造领域中被广泛用于标记零部件、装配体和机械系统的尺寸、距离、角度等信息。它们帮助工程师和设计师更好地理…

web自动化 -- selenium及应用

selenium简介 随着互联网的发展&#xff0c;前端技术不断变化&#xff0c;数据加载方式也不再是通过服务端渲染。现在许多网站使用接口或JSON数据通过JavaScript进行渲染。因此&#xff0c;使用requests来爬取内容已经不再适用&#xff0c;因为它只能获取服务器端网页的源码&am…

计算机网络体系的形成

目录 1、开放系统互连参考模型OSI/RM 2、两种国际标准 3、协议与划分层次 4、网络协议的三要素 5、划分层次 &#xff08;1&#xff09;文件发送模块使两个主机交换文件 &#xff08;2&#xff09;通信服务模块 &#xff08;3&#xff09;接入网络模块 6、分层带来的好…

Linux下Python调用C语言

一&#xff1a;Python调用C语言场景 1&#xff0c;已经写好的C语言代码&#xff0c;不容易用Python实现&#xff0c;想直接通过Python调用写好的C语言代码 2&#xff0c;C比Python快&#xff08;只是从语言层面&#xff0c;不能绝对说C程序就是比Python快&#xff09; 3&…