给出一个只包含0和1的二维矩阵,找出最大的全部元素都是1的长方形区域,返回该区域的面积。
思路:原想的是记下每个点的长度和高度就行了,然后相乘。但是想想下面的行需要知道上面的行开始的节点是否有用,所以要记下每个节点所在的连续线上最左边开始的位置是哪里。然后用右边减去即可。
<?php
function maximalRectangle($arrMatrix) {
if (empty($arrMatrix)) {
return 0;
}
$rows = count($arrMatrix);
$cols = count($arrMatrix[0]);
//想要求面积有三个值,左右及高度
$arrHeight = array();//存储每个列的高度,出现0,就从0再开始
$arrLeft = array();//存储每个行的连续左开始,各个行比较,只保存最大的
$arrRight = array();//存储每个行的连续右结束,各个行比较,只保存最小的
for ($i = 0; $i < $cols; $i ++) {
$arrRight[$i] = $cols;
}
$curLeft = 0;//当前的连续最左节点
$curRight = 0;//当前的连续最右节点
$max = 0;//最大面积
foreach ($arrMatrix as $arrRow) {
foreach ($arrRow as $key => $value) {
if ($value == 1) {
$arrHeight[$key] ++;
$arrLeft[$key] = max($arrLeft[$key], $curLeft);
} else {
$arrHeight[$key] = 0;//高度为0保证这个点一定算不出面积
$arrLeft[$key] = 0;//赋值最小的行左数,当下一行出现1时,不干扰
$curLeft = $key + 1;//把下一个开始的1连续开始,放在0的下一个
}
}
//注意这个右边界需要逆向来获得
for ($key = $cols - 1; $key >= 0; $key --) {
if ($arrRow[$key] == 1) {
$arrRight[$key] = min($arrRight[$key], $curRight);
} else {
$arrRight[$key] = $cols;//赋值最大的行右数,当下一行出现1时,不干扰
$curRight = $key;//把前一个1连续的结束,放在这个0的位置,算面积需要获得长度,放在这里不需要+1
}
}
foreach ($arrRow as $key => $value) {
$max = max($max, $arrHeight[$key] * ($arrRight[$key] - $arrLeft[$key]));//每一行都计算最大值
}
print json_encode($arrHeight). json_encode($arrLeft) . json_encode($arrRight) . "\n";
}
return $max;
}
$arr = [
[0,1,1,1,0],
[1,0,1,0,0],
[1,0,0,0,0],
];
$ret = maximalRectangle($arr);
print $ret;