全为 1 的最大尺寸矩形二进制子矩阵 |设置 2
给定一个大小为N*M的二进制矩阵mat[][] ,找到最大大小为全 1 的矩形二进制子矩阵。
例子:
Input: mat[][] = { {0, 1, 1, 0},
{1, 1, 1, 1},
{1, 1, 1, 1},
{1, 1, 0, 0} }
Output: 8
Explanation: The largest rectangle formed with only 1s is either: (0, 1) to (2, 2) or (1, 1) to (2, 3) which is
1 1 1 1
1 1 1 1
Input: mat[][] = { {0, 1, 1},
{1, 1, 1},
{0, 1, 1} }
Output: 6
Explanation: The largest rectangle with only 1’s is from (0, 1) to (2, 2) which is
1 1
1 1
1 1
方法:此方法使用直方图中最大矩形区域的概念。但是获得每行最大面积的方法与 Set-1 不同。
- Consider each row as the base of the histogram chart formed with all 1s.
- For each row, increase height of a bar by the amount of the previous row, only if the value in current row is 1 and calculate the largest rectangular area of that histogram.
- The largest rectangular area of a histogram among all possible base rows is the required are of the rectangle.
插图:
Consider the matrix:
mat[][] = 0 1 1 0
1 1 1 1
1 1 1 1
1 1 0 0
Calculate maxarea for the first row mat[0]
=> height row[0] = 0 1 1 0.
=> area = height* breadth = 1 * 2 = 2
Calculate maxarea for the first row mat[1]
=> update height of mat[1] with mat[0] i.e., mat[1][i] = mat[0][i] + 1 if mat[1][i] = 1, else 0
=> height row[1] = 1 2 2 1.
=> area = height* breadth = 2 * 2 = 4
Calculate maxarea for the first row mat[2]
=> update height of mat[2] with mat[1]. i.e., mat[2][i] = mat[1][i] + 1 if mat[2][i] = 1, else 0.
=> height row[2] = 2 3 3 2.
=> area = height* breadth = 2 * 4 = 8 (nextsmaller index of mat[2][0] = 4, and previous smaller index = 0. area = 2*(4 – 0))
Calculate maxarea for the first row mat[3]
=> update height of mat[3] with mat[2]. i.e., mat[3][i] = mat[2][i] + 1 if mat[3][i] = 1, else 0.
=> height row[3] = 3 4 0 0.
=> area = height* breadth = 3 * 2 = 6 (nextsmaller index of mat[3][0] = 2, and previous smaller index = 0. area = 3*(2 – 0))
=> here 3 4 0 0 is due to the reason that when mat[i][j] = 0 then don’t add previous heights into it.
Thus maxarea = max of(2, 4, 8, 6) = 8.
这种方法可以分为两部分:
- 计算每行的直方图高度作为基础。
- 运行循环以遍历行。
- 现在如果当前行不是第一行,则更新该单元格的高度,如下所示,
- 如果mat[i][j]不为零,则matrix[i][j] = matrix[i-1][j] + matrix[i][j] 。
- 否则mat[i][j] = 0 。
- 以每行为基数,计算直方图中最大矩形面积为 1。
- 首先计算每行的高度作为基数,如上所述。
- 创建两个数组nextSmallereElemen[]和prevouSmallerElement[]分别存储前一个较小元素和下一个较小元素的索引。请参阅本文以查找上一个和下一个较小的元素。
- 现在对于每个元素,通过将第 j 个元素作为 nextSmallereElemen[j] 和 prevouSmallerElement[j] 范围内的最小值并将其乘以nextSmallereElemen[j]和prevouSmallerElement [j] 的差来计算面积。
- 因此,高度将是给定输入数组中的第 j 个元素。宽度将是, breadth = nextSmallereElemen[j] – previousSmallerElement[j] 。
- 最后,找到所有区域中的最大值以获得所需的最大区域。
- 找到所有行中的最大面积,这将是矩形所需的面积。
以下是上述方法的实现:
C++
// C++ code for the above approach:
#include
using namespace std;
// Function to find next smaller element
vector nextsmallerelement(vector& arr,
int n)
{
stack st;
// For the elements which dont have
// next smaller element ans will be -1
st.push(-1);
// Store indices in output
vector right(n);
// Start from last index
for (int i = n - 1; i >= 0; i--) {
// If top element is sorted then
// no need to do anyrhing, just store
// the answer and push the
// current element in stack
if ((st.top() != -1)
&& arr[st.top()] < arr[i]) {
right[i] = st.top();
st.push(i);
}
else {
while ((st.top() != -1)
&& arr[st.top()]
>= arr[i]) {
st.pop();
}
right[i] = st.top();
st.push(i);
}
}
return right;
}
// Function to find previous smaller element
vector previousmallerelement(vector& arr,
int n)
{
stack st;
st.push(-1);
vector left(n);
// Start from first index
for (int i = 0; i < n; i++) {
if ((st.top() != -1)
&& arr[st.top()] < arr[i]) {
left[i] = st.top();
st.push(i);
}
else {
while ((st.top() != -1)
&& arr[st.top()]
>= arr[i]) {
st.pop();
}
left[i] = st.top();
st.push(i);
}
}
return left;
}
// Function to get the maximum area
// considering each row as the histogram base
int getMaxArea(vector& arr, int n)
{
vector right(n);
right = nextsmallerelement(arr, n);
// Find the smallest element than
// curr element in right side
vector left(n);
left = previousmallerelement(arr, n);
// Find the smallest element
// than curr element in left side
int maxarea = INT_MIN;
// Now the left and right vector have
// index of smallest elemnt in left and
// right respetively, thus the difference
// of right - left - 1 will give us
// breadth and thus
// area = height(curr==arr[i]) * breadth;
for (int i = 0; i < n; i++) {
int height = arr[i];
if (right[i] == -1) {
right[i] = n;
}
int breadth = right[i] - left[i] - 1;
maxarea = max(maxarea,
height * breadth);
}
return maxarea;
}
// Function to calculate
// the maximum area of rectangle
int maxRectangleArea(vector >& M,
int n, int m)
{
// Calculate maxarea for first row
int area = getMaxArea(M[0], m);
int maxarea = area;
for (int i = 1; i < n; i++) {
for (int j = 0; j < m; j++) {
if (M[i][j] != 0) {
// Add heights of previous rows
// into current
M[i][j] = M[i][j]
+ M[i - 1][j];
}
else {
// If current height is 0 then
// don't add previous heights
M[i][j] = 0;
}
}
maxarea = max(maxarea,
getMaxArea(M[i], m));
}
return maxarea;
}
// Driver code
int main()
{
int N = 4, M = 4;
vector > amt = {
{ 0, 1, 1, 0 },
{ 1, 1, 1, 1 },
{ 1, 1, 1, 1 },
{ 1, 1, 0, 0 },
};
cout << maxRectangleArea(amt, N, M);
return 0;
}
Javascript
8
时间复杂度: O(N * M)
辅助空间: O(M)