最大矩形

本文分析了一种解决寻找二维黑白位图中最大全白色矩形的算法,通过将问题转换为求解一维最大矩形并利用堆栈处理。首先将二维问题简化为一维,然后构建辅助矩阵C,记录每列从当前位置开始向上数1的个数,最终通过遍历矩阵C,应用一维策略找到最大面积矩形,时间复杂度为O(n^2)。
摘要由CSDN通过智能技术生成

###最大矩形

####原题
在一个位图中找面积最大的白色矩形:给你一个NxN的黑白位图,找一个面积最大的全白色的矩形。注意了,是一个矩形,不是任意一个白色相连的区域。你的算法能够达到的最好的时间复杂度是多少呢?

####分析
为了方便进行分析,我们假设黑色位置都是0,白色的位置都是1.题目的问题就转化为,找到一个最大的矩形,其中所有的元素都是1.

遇到这样的题目,该如何分析呢?这是一个矩形,是二维,是否是由一维的某些问题扩展而来的呢?一维的问题的解法,是否可以扩展到二维呢?我们看下面的题目:

在柱状图中找最大的矩形:给一组非负的整数来表示一个柱状图,设计一个算法找到最大面积的能适合到柱状图内的矩形。比如,对与这组数,1 2 3 4 1 ,有两种可能的方案,一种是适合到 2 3 4 内的矩形,面积是 23;另一种是适合到 3 4 内的矩形,面积是 32。你觉得能有O(n)算法吗?

一维的时候思路如下:

一个线性算法是用堆栈来保存当前可能的矩形(高度和起始位置)。从左到右扫描,对一个元素,如果 a)大于栈顶元素, push; b)小于的话,pop所有的大于它的元素,计算面积,更新最大值。这时如果堆栈空,push一个新的元素,高度等于当前元素,起始位置为0;否则,push当前元素高度和栈顶的起始位置。

这是一个很巧妙的解法,是否能够应用到二维的情况呢?针对如下例子,有矩阵A:

110010
011111
111110
001100

上面的这个矩阵,该如何转化为一维的情况处理呢?最直接的思路如下:

  • 第一行作为一维的情况处理;
  • 第一行、第二行,对应列相加,生成一个新的数组,然后应用一维的处理情况;
  • 第一行、第二行、第三行,对应列相加,生成一个新的数组,然后应用一维的处理情况;
  • …直到整个矩阵都包括在内;
  • 第二行作为一维的情况处理;
  • 第二行、第三行,对应列相加,生成一个新的数组,然后应用一维的处理情况;
  • …一次类推

上面的思路是可行的,但是时间复杂度是n^3的。如何进一步改进呢?思路也是从上面的过程中得到的。

生成新的矩阵C,C[i][j]表示第j列,从第i个元素开始,包括第i个元素,向上数,直到遇到0时,1的个数。则C为:

110010
021121
132230
003300

上面这个矩阵的构造,遍历一边A的全部元素即可。n^2的时间复杂度。这个矩阵的最大作用,就是将上面思路中,跨几行考虑的情况,都变为一行了。时间复杂度降了一个级别,每一行,应用一维处理处理的情况,就可以得到最终的结果。

将上面斜体的描述转换为如下步骤:(h, i),h表示C[i][j]的大小,可以理解为矩形的高度,i表示起始位置,第三行为例:

iC[i]栈操作最大值栈内容
01push (1,0)(1,0)
13push (3,1)(3,1)(1,0)
22pop (3,1),push (2,1)(2-1)*3=3(2,1)(1,0)
32什么都不做(2,1)(1,0)
43push(3,4)(3,4)(2,1)(1,0)
50pop(3,4)(5-4)*3=3(2,1)(1,0)
50pop(2,1)(5-1)*2=8(1,0)
50pop(1,0)(5-0)*1=5

则得到这一行的最大值为8。

总结算法过程如下:

  • 初始(h,0),入栈;
  • 遍历后续元素:
    • 如果h > h_top, 则入栈;
    • 如果h = h_top, 则不进行任何操作;
    • 如果h < h_top, 出栈,直到栈顶元素的高度小于h,每次出栈,更新最大值(i - i_pop)*h_pop > max ? (i - i_pop)*h_pop : max;此时如果h>h_top,则push (h, i_lastpop),如果栈为空,则push (h, 0).
  • 直到元素遍历完毕
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值