📌  相关文章
📜  在允许交换列的情况下找到最大的 1 矩形

📅  最后修改于: 2022-05-13 01:57:23.771000             🧑  作者: Mango

在允许交换列的情况下找到最大的 1 矩形

给定一个包含 0 和 1 的矩阵,找出矩阵中所有 1 的最大矩形。可以通过交换给定矩阵的任何一对列来形成矩形。
例子:

Input: bool mat[][] = { {0, 1, 0, 1, 0},
                        {0, 1, 0, 1, 1},
                        {1, 1, 0, 1, 0}
                      };
Output: 6
The largest rectangle's area is 6. The rectangle 
can be formed by swapping column 2 with 3
The matrix after swapping will be
     0 0 1 1 0
     0 0 1 1 1
     1 0 1 1 0


Input: bool mat[R][C] = { {0, 1, 0, 1, 0},
                         {0, 1, 1, 1, 1},
                         {1, 1, 1, 0, 1},
                         {1, 1, 1, 1, 1}
                      };
Output: 9

这个想法是使用辅助矩阵来存储每列中连续 1 的计数。一旦我们有了这些计数,我们就按照计数的非递增顺序对所有辅助矩阵行进行排序。最后遍历已排序的行,找到最大面积。
注意:形成辅助矩阵后,每一行变得独立,因此我们可以独立交换或排序每一行。这是因为我们只能交换列,所以我们使每一行独立,并找到行和列可能的矩形最大面积.
以下是上述第一个示例的详细步骤。
第1步:首先,计算没有。每列中连续的 1。辅助数组 hist[][] 用于存储连续 1 的计数。所以对于上面的第一个例子, hist[R][C] 的内容将是

0 1 0 1 0
    0 2 0 2 1
    1 3 0 3 0

这一步的时间复杂度是O(R*C)
第 2 步:以非递增方式对行进行排序。在排序步骤之后,矩阵 hist[][] 将是

1 1 0 0 0
    2 2 1 0 0
    3 3 1 0 0

这一步可以在 O(R * (R + C)) 中完成。由于我们知道值在 0 到 R 的范围内,我们可以对每一行使用计数排序。
排序实际上是列的交换。如果我们查看第 2 步下的第 3 行:
3 3 1 0 0
排序后的行对应于交换列,以便首先放置具有最高可能矩形的列,然后是允许第二高矩形的列,依此类推。因此,在示例中,有 2 列可以形成一个高度为 3 的矩形。这使得面积为 3*2=6。如果我们尝试使矩形更宽,则高度会下降到 1,因为没有剩余的列允许在第 3 行使用更高的矩形。
步骤 3:遍历 hist[][] 的每一行并检查最大区域。由于每一行都按 1 的计数排序,因此可以通过将列数乘以 hist[i][j] 中的值来计算当前区域。这一步也需要 O(R * C) 时间。
下面是基于上述思想的实现。

C++
// C++ program to find the largest rectangle of 1's with swapping
// of columns allowed.
#include 
#define R 3
#define C 5
 
using namespace std;
 
// Returns area of the largest rectangle of 1's
int maxArea(bool mat[R][C])
{
    // An auxiliary array to store count of consecutive 1's
    // in every column.
    int hist[R + 1][C + 1];
 
    // Step 1: Fill the auxiliary array hist[][]
    for (int i = 0; i < C; i++) {
        // First row in hist[][] is copy of first row in mat[][]
        hist[0][i] = mat[0][i];
 
        // Fill remaining rows of hist[][]
        for (int j = 1; j < R; j++)
            hist[j][i] = (mat[j][i] == 0) ? 0 : hist[j - 1][i] + 1;
    }
 
    // Step 2: Sort columns of hist[][] in non-increasing order
    for (int i = 0; i < R; i++) {
        int count[R + 1] = { 0 };
 
        // counting occurrence
        for (int j = 0; j < C; j++)
            count[hist[i][j]]++;
 
        // Traverse the count array from right side
        int col_no = 0;
        for (int j = R; j >= 0; j--) {
            if (count[j] > 0) {
                for (int k = 0; k < count[j]; k++) {
                    hist[i][col_no] = j;
                    col_no++;
                }
            }
        }
    }
 
    // Step 3: Traverse the sorted hist[][] to find maximum area
    int curr_area, max_area = 0;
    for (int i = 0; i < R; i++) {
        for (int j = 0; j < C; j++) {
            // Since values are in decreasing order,
            // The area ending with cell (i, j) can
            // be obtained by multiplying column number
            // with value of hist[i][j]
            curr_area = (j + 1) * hist[i][j];
            if (curr_area > max_area)
                max_area = curr_area;
        }
    }
    return max_area;
}
 
// Driver program
int main()
{
    bool mat[R][C] = { { 0, 1, 0, 1, 0 },
                       { 0, 1, 0, 1, 1 },
                       { 1, 1, 0, 1, 0 } };
    cout << "Area of the largest rectangle is " << maxArea(mat);
    return 0;
}


Java
// Java program to find the largest rectangle of
// 1's with swapping of columns allowed.
class GFG {
 
    static final int R = 3;
    static final int C = 5;
 
    // Returns area of the largest rectangle of 1's
    static int maxArea(int mat[][])
    {
        // An auxiliary array to store count of consecutive 1's
        // in every column.
        int hist[][] = new int[R + 1][C + 1];
 
        // Step 1: Fill the auxiliary array hist[][]
        for (int i = 0; i < C; i++)
        {
            // First row in hist[][] is copy of first row in mat[][]
            hist[0][i] = mat[0][i];
 
            // Fill remaining rows of hist[][]
            for (int j = 1; j < R; j++)
            {
                hist[j][i] = (mat[j][i] == 0) ? 0 : hist[j - 1][i] + 1;
            }
        }
 
        // Step 2: Sort rows of hist[][] in non-increasing order
        for (int i = 0; i < R; i++)
        {
            int count[] = new int[R + 1];
 
            // counting occurrence
            for (int j = 0; j < C; j++)
            {
                count[hist[i][j]]++;
            }
 
            // Traverse the count array from right side
            int col_no = 0;
            for (int j = R; j >= 0; j--)
            {
                if (count[j] > 0)
                {
                    for (int k = 0; k < count[j]; k++)
                    {
                        hist[i][col_no] = j;
                        col_no++;
                    }
                }
            }
        }
 
        // Step 3: Traverse the sorted hist[][] to find maximum area
        int curr_area, max_area = 0;
        for (int i = 0; i < R; i++)
        {
            for (int j = 0; j < C; j++)
            {
                // Since values are in decreasing order,
                // The area ending with cell (i, j) can
                // be obtained by multiplying column number
                // with value of hist[i][j]
                curr_area = (j + 1) * hist[i][j];
                if (curr_area > max_area)
                {
                    max_area = curr_area;
                }
            }
        }
        return max_area;
    }
 
    // Driver Code
    public static void main(String[] args)
    {
        int mat[][] = {{0, 1, 0, 1, 0},
                       {0, 1, 0, 1, 1},
                       {1, 1, 0, 1, 0}};
        System.out.println("Area of the largest rectangle is " + maxArea(mat));
    }
}
 
// This code is contributed by PrinciRaj1992


Python3
# Python 3 program to find the largest
# rectangle of 1's with swapping
# of columns allowed.
 
R = 3
C = 5
 
# Returns area of the largest
# rectangle of 1's
def maxArea(mat):
     
    # An auxiliary array to store count
    # of consecutive 1's in every column.
    hist = [[0 for i in range(C + 1)]
               for i in range(R + 1)]
 
    # Step 1: Fill the auxiliary array hist[][]
    for i in range(0, C, 1):
         
        # First row in hist[][] is copy of
        # first row in mat[][]
        hist[0][i] = mat[0][i]
 
        # Fill remaining rows of hist[][]
        for j in range(1, R, 1):
            if ((mat[j][i] == 0)):
                hist[j][i] = 0
            else:
                hist[j][i] = hist[j - 1][i] + 1
 
    # Step 2: Sort rows of hist[][] in
    # non-increasing order
    for i in range(0, R, 1):
        count = [0 for i in range(R + 1)]
 
        # counting occurrence
        for j in range(0, C, 1):
            count[hist[i][j]] += 1
 
        # Traverse the count array from
        # right side
        col_no = 0
        j = R
        while(j >= 0):
            if (count[j] > 0):
                for k in range(0, count[j], 1):
                    hist[i][col_no] = j
                    col_no += 1
 
            j -= 1
             
    # Step 3: Traverse the sorted hist[][]
    # to find maximum area
    max_area = 0
    for i in range(0, R, 1):
        for j in range(0, C, 1):
             
            # Since values are in decreasing order,
            # The area ending with cell (i, j) can
            # be obtained by multiplying column number
            # with value of hist[i][j]
            curr_area = (j + 1) * hist[i][j]
            if (curr_area > max_area):
                max_area = curr_area
 
    return max_area
 
# Driver Code
if __name__ == '__main__':
    mat = [[0, 1, 0, 1, 0],
           [0, 1, 0, 1, 1],
           [1, 1, 0, 1, 0]]
    print("Area of the largest rectangle is",
                                maxArea(mat))
     
# This code is contributed by
# Shashank_Sharma


C#
// C# program to find the largest rectangle of
// 1's with swapping of columns allowed.
using System;
 
 class GFG
{
 
    static readonly int R = 3;
    static readonly int C = 5;
 
    // Returns area of the largest
    // rectangle of 1's
    static int maxArea(int [,]mat)
    {
        // An auxiliary array to store count
        // of consecutive 1's in every column.
        int [,]hist = new int[R + 1, C + 1];
 
        // Step 1: Fill the auxiliary array hist[,]
        for (int i = 0; i < C; i++)
        {
            // First row in hist[,] is copy of
            // first row in mat[,]
            hist[0, i] = mat[0, i];
 
            // Fill remaining rows of hist[,]
            for (int j = 1; j < R; j++)
            {
                hist[j, i] = (mat[j, i] == 0) ? 0 :
                                hist[j - 1, i] + 1;
            }
        }
 
        // Step 2: Sort rows of hist[,]
        // in non-increasing order
        for (int i = 0; i < R; i++)
        {
            int []count = new int[R + 1];
 
            // counting occurrence
            for (int j = 0; j < C; j++)
            {
                count[hist[i, j]]++;
            }
 
            // Traverse the count array from right side
            int col_no = 0;
            for (int j = R; j >= 0; j--)
            {
                if (count[j] > 0)
                {
                    for (int k = 0; k < count[j]; k++)
                    {
                        hist[i, col_no] = j;
                        col_no++;
                    }
                }
            }
        }
 
        // Step 3: Traverse the sorted hist[,]
        // to find maximum area
        int curr_area, max_area = 0;
        for (int i = 0; i < R; i++)
        {
            for (int j = 0; j < C; j++)
            {
 
                // Since values are in decreasing order,
                // The area ending with cell (i, j) can
                // be obtained by multiplying column number
                // with value of hist[i,j]
                curr_area = (j + 1) * hist[i, j];
                if (curr_area > max_area)
                {
                    max_area = curr_area;
                }
            }
        }
        return max_area;
    }
 
    // Driver Code
    public static void Main()
    {
        int [,]mat = {{0, 1, 0, 1, 0},
                    {0, 1, 0, 1, 1},
                    {1, 1, 0, 1, 0}};
        Console.WriteLine("Area of the largest rectangle is " +
                                                maxArea(mat));
    }
}
 
//This code is contributed by 29AjayKumar


Javascript


输出:

Area of the largest rectangle is 6