📜  二维网格中正方形的最大周长

📅  最后修改于: 2021-09-22 10:11:46             🧑  作者: Mango

给定一个大小为N * M的整数矩阵mat[][] 。任务是找到矩阵中正方形的最大周长。正方形的周长定义为正方形边上所有值的总和。
例子:

朴素的方法:一个简单的解决方案是在给定的矩阵mat[][]内生成所有可能的正方形,然后找到它们的周长并从中取出最大值。
有效的方法:

  • 要找到正方形的周长,应该知道边长。
  • 这里的长度被描述为特定行和列上元素的总和。
  • 将创建两个大小为N * M的矩阵,该矩阵将存储原始矩阵行的前缀和和列的前缀和,以便可以在恒定时间内计算边长。
  • 将有两个嵌套循环,一个从1N ,另一个从1M来找到正方形的左角(左上角),一个循环是min(N – i, M – j) ,它会告诉我们使用正方形的大小并确保索引不会超过矩阵的大小。

下面是上述方法的实现:

C++
// C++ implementation of the approach
#include 
using namespace std;
 
// Function to calculate the perfix sum of the
// rows and the columns of the given matrix
void perfix_calculate(vector >& A,
                      vector >& row,
                      vector >& col)
{
 
    // Number of rows and cols
    int n = (int)A.size();
    int m = (int)A[0].size();
 
    // First column of the row prefix array
    for (int i = 0; i < n; ++i) {
        row[i][0] = A[i][0];
    }
 
    // Update the prefix sum for the rows
    for (int i = 0; i < n; ++i) {
        for (int j = 1; j < m; ++j) {
            row[i][j] = row[i][j - 1]
                        + A[i][j];
        }
    }
 
    // First row of the column prefix array
    for (int i = 0; i < m; ++i) {
        col[0][i] = A[0][i];
    }
 
    // Update the prefix sum for the columns
    for (int i = 0; i < m; ++i) {
        for (int j = 1; j < n; ++j) {
            col[j][i] = A[j][i]
                        + col[j - 1][i];
        }
    }
}
 
// Function to return the perimeter
// of the square having top-left corner
// at (i, j) and size k
int perimeter(int i, int j, int k,
              vector >& row,
              vector >& col,
              vector >& A)
{
 
    // i and j represent the top left
    // corner of the square and
    // k is the size
    int row_s, col_s;
 
    // Get the upper row sum
    if (j == 0)
        row_s = 0;
    else
        row_s = row[i][j - 1];
 
    // Get the left column sum
    if (i == 0)
        col_s = 0;
    else
        col_s = col[i - 1][j];
 
    int upper_row = row[i][j + k] - row_s;
    int left_col = col[i + k][j] - col_s;
 
    // At the distance of k in
    // both direction
    if (j == 0)
        row_s = 0;
    else
        row_s = row[i + k][j - 1];
 
    if (i == 0)
        col_s = 0;
    else
        col_s = col[i - 1][j + k];
 
    int lower_row = row[i + k][j + k] - row_s;
    int right_col = col[i + k][j + k] - col_s;
 
    // The perimeter will be
    // sum of all the values
    int sum = upper_row
              + lower_row
              + left_col
              + right_col;
 
    // Since all the corners are
    // included twice, they need to
    // be subtract from the sum
    sum -= (A[i][j]
            + A[i + k][j]
            + A[i][j + k]
            + A[i + k][j + k]);
 
    return sum;
}
 
// Function to return the maximum perimeter
// of a square in the given matrix
int maxPerimeter(vector >& A)
{
 
    // Number of rows and cols
    int n = (int)A.size();
    int m = (int)A[0].size();
 
    vector > row(n, vector(m, 0));
    vector > col(n, vector(m, 0));
 
    // Function call to calculate
    // the prefix sum of rows and cols
    perfix_calculate(A, row, col);
 
    // To store the maximum perimeter
    int maxPer = 0;
 
    // Nested loops to choose the top-left
    // corner of the square
    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < m; ++j) {
 
            // Loop for the size of the square
            for (int k = 0; k < min(n - i, m - j); ++k) {
 
                // Get the perimeter of the current square
                int perimtr = perimeter(i, j, k, row, col, A);
 
                // Update the maximum perimeter so far
                maxPer = max(maxPer, perimtr);
            }
        }
    }
 
    return maxPer;
}
 
// Driver code
int main()
{
    vector > A = {
        { 1, 1, 0 },
        { 1, 1, 1 },
        { 0, 1, 1 }
    };
 
    cout << maxPerimeter(A);
 
    return 0;
}


Java
// Java implementation of the approach
import java.util.*;
 
class GFG
{
 
// Function to calculate the perfix sum of the
// rows and the columns of the given matrix
static void perfix_calculate(int [][] A,
                    int [][] row,
                    int [][] col)
{
 
    // Number of rows and cols
    int n = (int)A.length;
    int m = (int)A[0].length;
 
    // First column of the row prefix array
    for (int i = 0; i < n; ++i)
    {
        row[i][0] = A[i][0];
    }
 
    // Update the prefix sum for the rows
    for (int i = 0; i < n; ++i)
    {
        for (int j = 1; j < m; ++j)
        {
            row[i][j] = row[i][j - 1]
                        + A[i][j];
        }
    }
 
    // First row of the column prefix array
    for (int i = 0; i < m; ++i)
    {
        col[0][i] = A[0][i];
    }
 
    // Update the prefix sum for the columns
    for (int i = 0; i < m; ++i)
    {
        for (int j = 1; j < n; ++j)
        {
            col[j][i] = A[j][i]
                        + col[j - 1][i];
        }
    }
}
 
// Function to return the perimeter
// of the square having top-left corner
// at (i, j) and size k
static int perimeter(int i, int j, int k,
                int [][] row, int [][] col,
                int [][] A)
{
 
    // i and j represent the top left
    // corner of the square and
    // k is the size
    int row_s, col_s;
 
    // Get the upper row sum
    if (j == 0)
        row_s = 0;
    else
        row_s = row[i][j - 1];
 
    // Get the left column sum
    if (i == 0)
        col_s = 0;
    else
        col_s = col[i - 1][j];
 
    int upper_row = row[i][j + k] - row_s;
    int left_col = col[i + k][j] - col_s;
 
    // At the distance of k in
    // both direction
    if (j == 0)
        row_s = 0;
    else
        row_s = row[i + k][j - 1];
 
    if (i == 0)
        col_s = 0;
    else
        col_s = col[i - 1][j + k];
 
    int lower_row = row[i + k][j + k] - row_s;
    int right_col = col[i + k][j + k] - col_s;
 
    // The perimeter will be
    // sum of all the values
    int sum = upper_row + lower_row +
                left_col + right_col;
 
    // Since all the corners are
    // included twice, they need to
    // be subtract from the sum
    sum -= (A[i][j] + A[i + k][j] +
             A[i][j + k] + A[i + k][j + k]);
 
    return sum;
}
 
// Function to return the maximum perimeter
// of a square in the given matrix
static int maxPerimeter(int [][] A)
{
 
    // Number of rows and cols
    int n = (int)A.length;
    int m = (int)A[0].length;
 
    int [][] row = new int[n][m];
    int [][] col = new int[n][m];
 
    // Function call to calculate
    // the prefix sum of rows and cols
    perfix_calculate(A, row, col);
 
    // To store the maximum perimeter
    int maxPer = 0;
 
    // Nested loops to choose the top-left
    // corner of the square
    for (int i = 0; i < n; ++i)
    {
        for (int j = 0; j < m; ++j)
        {
 
            // Loop for the size of the square
            for (int k = 0; k < Math.min(n - i, m - j); ++k)
            {
 
                // Get the perimeter of the current square
                int perimtr = perimeter(i, j, k,
                                        row, col, A);
 
                // Update the maximum perimeter so far
                maxPer = Math.max(maxPer, perimtr);
            }
        }
    }
 
    return maxPer;
}
 
// Driver code
public static void main(String[] args)
{
    int [][] A = {
        { 1, 1, 0 },
        { 1, 1, 1 },
        { 0, 1, 1 }
    };
 
    System.out.print(maxPerimeter(A));
}
}
 
// This code is contributed by PrinciRaj1992


Python3
# Python3 implementation of the approach
 
# Function to calculate the perfix sum of the
# rows and the columns of the given matrix
def perfix_calculate(A, row, col):
     
    # Number of rows and cols
    n = len(A)
    m = len(A[0])
 
    # First column of the row prefix array
    for i in range(n):
        row[i][0] = A[i][0]
 
    # Update the prefix sum for the rows
    for i in range(n):
        for j in range(1, m):
            row[i][j] = row[i][j - 1]+ A[i][j]
 
    # First row of the column prefix array
    for i in range(m):
        col[0][i] = A[0][i]
 
    # Update the prefix sum for the columns
    for i in range(m):
        for j in range(1, m):
            col[j][i] = A[j][i] + col[j - 1][i]
 
# Function to return the perimeter
# of the square having top-left corner
# at (i, j) and size k
def perimeter(i, j, k, row, col, A):
 
    # i and j represent the top left
    # corner of the square and
    # k is the size
    row_s, col_s = 0, 0
 
    # Get the upper row sum
    if (j == 0):
        row_s = 0
    else:
        row_s = row[i][j - 1]
 
    # Get the left column sum
    if (i == 0):
        col_s = 0
    else:
        col_s = col[i - 1][j]
 
    upper_row = row[i][j + k] - row_s
    left_col = col[i + k][j] - col_s
 
    # At the distance of k in
    # both direction
    if (j == 0):
        row_s = 0
    else:
        row_s = row[i + k][j - 1]
 
    if (i == 0):
        col_s = 0
    else:
        col_s = col[i - 1][j + k]
 
    lower_row = row[i + k][j + k] - row_s
    right_col = col[i + k][j + k] - col_s
 
    # The perimeter will be
    # sum of all the values
    sum = upper_row + lower_row + \
           left_col + right_col
 
    # Since all the corners are
    # included twice, they need to
    # be subtract from the sum
    sum -= (A[i][j] + A[i + k][j] + \
            A[i][j + k] + A[i + k][j + k])
 
    return sum
 
# Function to return the maximum perimeter
# of a square in the given matrix
def maxPerimeter(A):
 
    # Number of rows and cols
    n = len(A)
    m = len(A[0])
 
    row = [[0 for i in range(m)]
              for i in range(n)]
    col = [[0 for i in range(m)]
              for i in range(n)]
 
    # Function call to calculate
    # the prefix sum of rows and cols
    perfix_calculate(A, row, col)
 
    # To store the maximum perimeter
    maxPer = 0
 
    # Nested loops to choose the top-left
    # corner of the square
    for i in range(n):
        for j in range(m):
 
            # Loop for the size of the square
            for k in range(min(n - i, m - j)):
 
                # Get the perimeter of the current square
                perimtr = perimeter(i, j, k,
                                    row, col, A)
 
                # Update the maximum perimeter so far
                maxPer = max(maxPer, perimtr)
 
    return maxPer
 
# Driver code
A = [[ 1, 1, 0 ],
     [ 1, 1, 1 ],
     [ 0, 1, 1 ]]
 
print(maxPerimeter(A))
 
# This code is contributed by Mohit Kumar


C#
// C# implementation of the approach
using System;
 
class GFG
{
 
// Function to calculate the perfix sum of the
// rows and the columns of the given matrix
static void perfix_calculate(int [,] A,
                    int [,] row,
                    int [,] col)
{
 
    // Number of rows and cols
    int n = (int)A.GetLength(0);
    int m = (int)A.GetLength(1);
 
    // First column of the row prefix array
    for (int i = 0; i < n; ++i)
    {
        row[i, 0] = A[i, 0];
    }
 
    // Update the prefix sum for the rows
    for (int i = 0; i < n; ++i)
    {
        for (int j = 1; j < m; ++j)
        {
            row[i, j] = row[i, j - 1]
                        + A[i, j];
        }
    }
 
    // First row of the column prefix array
    for (int i = 0; i < m; ++i)
    {
        col[0, i] = A[0, i];
    }
 
    // Update the prefix sum for the columns
    for (int i = 0; i < m; ++i)
    {
        for (int j = 1; j < n; ++j)
        {
            col[j, i] = A[j, i]
                        + col[j - 1, i];
        }
    }
}
 
// Function to return the perimeter
// of the square having top-left corner
// at (i, j) and size k
static int perimeter(int i, int j, int k,
                int [,] row, int [,] col,
                int [,] A)
{
 
    // i and j represent the top left
    // corner of the square and
    // k is the size
    int row_s, col_s;
 
    // Get the upper row sum
    if (j == 0)
        row_s = 0;
    else
        row_s = row[i, j - 1];
 
    // Get the left column sum
    if (i == 0)
        col_s = 0;
    else
        col_s = col[i - 1, j];
 
    int upper_row = row[i, j + k] - row_s;
    int left_col = col[i + k, j] - col_s;
 
    // At the distance of k in
    // both direction
    if (j == 0)
        row_s = 0;
    else
        row_s = row[i + k, j - 1];
 
    if (i == 0)
        col_s = 0;
    else
        col_s = col[i - 1, j + k];
 
    int lower_row = row[i + k, j + k] - row_s;
    int right_col = col[i + k, j + k] - col_s;
 
    // The perimeter will be
    // sum of all the values
    int sum = upper_row + lower_row +
                left_col + right_col;
 
    // Since all the corners are
    // included twice, they need to
    // be subtract from the sum
    sum -= (A[i, j] + A[i + k, j] +
            A[i, j + k] + A[i + k, j + k]);
 
    return sum;
}
 
// Function to return the maximum perimeter
// of a square in the given matrix
static int maxPerimeter(int [,] A)
{
 
    // Number of rows and cols
    int n = (int)A.GetLength(0);
    int m = (int)A.GetLength(1);
 
    int [,] row = new int[n, m];
    int [,] col = new int[n, m];
 
    // Function call to calculate
    // the prefix sum of rows and cols
    perfix_calculate(A, row, col);
 
    // To store the maximum perimeter
    int maxPer = 0;
 
    // Nested loops to choose the top-left
    // corner of the square
    for (int i = 0; i < n; ++i)
    {
        for (int j = 0; j < m; ++j)
        {
 
            // Loop for the size of the square
            for (int k = 0; k < Math.Min(n - i, m - j); ++k)
            {
 
                // Get the perimeter of the current square
                int perimtr = perimeter(i, j, k,
                                        row, col, A);
 
                // Update the maximum perimeter so far
                maxPer = Math.Max(maxPer, perimtr);
            }
        }
    }
    return maxPer;
}
 
// Driver code
public static void Main(String[] args)
{
    int [,] A = {{ 1, 1, 0 },
                { 1, 1, 1 },
                { 0, 1, 1 }};
 
    Console.Write(maxPerimeter(A));
}
}
 
// This code is contributed by PrinciRaj1992


Javascript


输出:
6

时间复杂度: O(N * M * min(N, M))

如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程学生竞争性编程现场课程