给定一个填充有0和1的二维二进制矩阵,找到仅包含1的最大矩形并返回其面积。

public class MaximalRectangle
{
public MaximalRectangle(){}

public int maximalRectangle(char[][] matrix) 
{   
	if(matrix.length == 0 || matrix[0].length == 0)
    {return 0;}
    
	int maxarea= 0;
	int[][] temp= new int[matrix.length][matrix[0].length];
	
	for(int i=0;i<matrix.length;i++)
	{
		for(int j=0;j<matrix[0].length;j++)
		{
			if(i==0)
			{temp[i][j]= matrix[i][j] - 48;}
			else
			{
				temp[i][j]= (matrix[i][j] == '0') ? 0 : (temp[i-1][j] + 1);
			}
			
			int min= temp[i][j];
			for(int k=j;k>=0;k--)
			{
				if(min == 0) {break;}
				if(min > temp[i][k])
				{min= temp[i][k];}
				maxarea= Math.max(maxarea, min * (j - k + 1));
			}
		}
	}
	return maxarea;
}

}

这个问题可以使用动态规划和栈两种方法来解决。 ### 动态规划 假设矩阵的大小为 $m \times n$,我们可以定义一个新的矩阵 $dp$,其中 $dp_{i,j}$ 表示以 $(i,j)$ 为右下角的最大矩形面积。如果原矩阵中 $(i,j)$ 的值为 0,则 $dp_{i,j} = 0$;如果 $(i,j)$ 的值为 1,则可以根据 $(i-1,j)$ 和 $(i,j-1)$ 的值来计算 $dp_{i,j}$: $$ dp_{i,j} = \begin{cases} 0 & \text{if } matrix_{i,j} = 0 \\ 1 + \min(dp_{i-1,j}, dp_{i,j-1}, dp_{i-1,j-1}) & \text{if } matrix_{i,j} = 1 \end{cases} $$ 其中 $\min(dp_{i-1,j}, dp_{i,j-1}, dp_{i-1,j-1})$ 表示以 $(i,j)$ 为右下角的最大正方形的边长,因为只有在 $(i-1,j)$、$(i,j-1)$ 和 $(i-1,j-1)$ 这三个位置都存在正方形时,$(i,j)$ 才能作为右下角构成更大的矩形。 最后,我们可以遍历整个 $dp$ 数组,找到最大面积即可。 时间复杂度为 $O(mn)$,空间复杂度为 $O(mn)$。 ### 栈 该方法的主要思路是使用单调栈。我们可以将每一行看作一个直方图,每个位置的高度为从这个位置向上连续的 1 的个数。例如,对于下面的矩阵: ``` 1 0 1 0 0 1 0 1 1 1 1 1 1 1 1 1 0 0 1 0 ``` 第一行的直方图为 [1, 0, 1, 0, 0],第二行的直方图为 [2, 0, 2, 1, 1],第三行的直方图为 [3, 1, 3, 2, 2],第四行的直方图为 [4, 0, 0, 3, 0]。 接下来,我们对于每一行都可以使用单调栈来计算以当前行为底的最大矩形面积。具体来说,我们维护一个单调递增的栈 $stack$,并且在遍历到每个位置时,执行以下操作: 1. 如果当前位置的高度大于栈顶元素的高度,将当前位置入栈; 2. 否则,将栈顶元素出栈,并计算以该栈顶元素为高度、以当前位置和栈顶元素之间的宽度为长度的最大矩形面积。具体来说,我们可以通过 $stack$ 的栈顶元素的下标 $j$ 和当前位置的下标 $i$,计算出矩形的宽度为 $i - stack[-1] - 1$,然后矩形面积为高度乘以宽度; 3. 重复步骤 2,直到栈为空或者当前位置的高度大于栈顶元素的高度,然后将当前位置入栈。 在遍历完所有行之后,我们可以得到以每一行为底的最大矩形面积,最后取最大值即可。 时间复杂度为 $O(mn)$,空间复杂度为 $O(n)$。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值