【ZUOSHEN】9、求最大子矩阵的大小

要求

给定一个整型矩阵map,其中的值只有0和1两种,求其中全是1的所有矩形区域中,最大的矩形区域为1的数量。

举例1
在这里插入图片描述
其中,最大的矩形区域有3个1,所以返回3。

举例2:
在这里插入图片描述
其中,最大的矩形区域有6个1,所以返回6。

思路

假设矩阵的 – 行数:N,列数:M

时间复杂度为:O(N×2M) -- O(N×M)

主要部分

以每一行作切割,统计当前行作为底的情况下,每个位置往上连续1的数量,用数组height[M]保存

举例:
在这里插入图片描述

  • 第1行切割后 {1 0 1 1}

    👉 height={1,0,1,1}

  • 第2行切割后{1 1 1 1}

    👉 height={2,1,2,2}

  • 第3行切割后{1 1 1 0}

    👉 height={3,2,3,0}

👀 怎么确定height[j]?

核心代码:

height[j]=map[i][j]==0?0:height[j]+1


当map这一行的某个位置元素为0, 那这边对应的height[j] = 0, 若不为0,那这边对应的height[j]为上一次的height[j]+ 1

针对每一次得到的height[M]都要去看一下目前拿它作为底可以有多大的矩形面积?

👉 于是,将每一次的 height[M]作为参数传入一个特定的函数取名为maxRecFromButton,即可拿到该值

👉 注意,该值只是每一行得到的height[M]算得的最大值,每一行都不一样,因此还需要选出最大的那一个作为结果返回


次要部分 – maxRecFromButton函数

要做到时间复杂度为O(M), 需要点技巧!

对于height[M], 可以将其想象为一张直方图,如 height={3,4,5,4,3,6},对应的直方图如下,将每个height[j]想象成一个柱子,然后求出每一根柱子向左向右扩展出去的最大矩形
在这里插入图片描述

核心思想:

考查每一根柱子最大能扩多大,这个行为的实质就是找到柱子左边离它最近且小于它的柱子位置在哪里以及右边离它最近且小于等于它的柱子位置在哪里【此时不用单调栈结构更待何时?】

微妙的是👉为什么向右要把等于包含进去呢?我认为这里可能一方面为了简化一下栈中的元素类型,使其可以是int型而不用搞成队列型,另一方面向右遍历遇到和前面相等的柱子总会更新一下面积最大值

这里的单调栈与上一题的有一丝丝的区别,关键是将上一题中 -1 的用途以及出栈和入栈条件搞清

  • 对于柱子 j 而言,分别向左和向右能扩展到的位置会在哪里呢?

    用单调栈结构

    • 左边的位置是离柱子j最近且小于它的高度的那个位置k再加1
    • 右边的位置是离柱子j最近且小于它的高度的那个位置i再减1
  • 找到了两个位置,矩形面积怎么算?

    假设我们找到了柱子j左边离它最近且小于它的位置k和其右边离它最近且小于等于它的位置i, 那对于柱子 j 这种高度的柱子,此刻能找到的最大矩形面积为 :

    recSize = (i - k -1) * height[j]

在全部找完之前,右边找到的位置 i 其实有可能作废,因为搞不好height[i+1] = height[j],所以对于柱子j,i往往可能要等最后才能彻底定下来

用例子的图解直观感受一下:

image-20220628192128272

这里注意遍历过程中的i值确定和遍历结束后直接让i = M的操作,因为最后留在栈里的是没有找到右边的扩展位置的,那我们可以人为假设在最右柱子的右侧还有个高度为0的柱子,位置为M, 而此时求面积的公式中i将替换成M

代码

#include <iostream>
#include <stack>
#include <algorithm>

using namespace std;

int maxRecFromButton(int height[],int n);

int maxRecsize(int N,
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值