Open In App

Maximum perimeter of a square in a 2D grid

Given a matrix of integers mat[][] of size N * M. The task is to find the maximum perimeter of a square in the matrix. The perimeter of a square is defined as the sum of all the values lying on the sides of the square.
Examples: 
 

Input: mat[][] = { 
{-3, -2, 7}, 
{-4, 6, 0}, 
{-4, 8, 2}} 
Output: 16 
The maximum perimeter square is 
{6, 0} 
{8, 2}
Input: mat[][] = { 
{1, 1, 0}, 
{1, 1, 1}, 
{0, 1, 1}} 
Output:
 



 

Naive approach: A simple solution is to generate all the square that can be possible inside the given matrix mat[][] and then find their perimeter and take the maximum out of them.
Efficient approach: 
 



Below is the implementation of the above approach: 
 




// C++ implementation of the approach
#include <bits/stdc++.h>
using namespace std;
 
// Function to calculate the prefix sum of the
// rows and the columns of the given matrix
void prefix_calculate(vector<vector<int> >& A,
                      vector<vector<int> >& row,
                      vector<vector<int> >& 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<vector<int> >& row,
              vector<vector<int> >& col,
              vector<vector<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
int maxPerimeter(vector<vector<int> >& A)
{
 
    // Number of rows and cols
    int n = (int)A.size();
    int m = (int)A[0].size();
 
    vector<vector<int> > row(n, vector<int>(m, 0));
    vector<vector<int> > col(n, vector<int>(m, 0));
 
    // Function call to calculate
    // the prefix sum of rows and cols
    prefix_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<vector<int> > A = {
        { 1, 1, 0 },
        { 1, 1, 1 },
        { 0, 1, 1 }
    };
 
    cout << maxPerimeter(A);
 
    return 0;
}




// Java implementation of the approach
import java.util.*;
 
class GFG
{
 
// Function to calculate the prefix sum of the
// rows and the columns of the given matrix
static void prefix_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
    prefix_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 implementation of the approach
 
# Function to calculate the prefix sum of the
# rows and the columns of the given matrix
def prefix_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
    prefix_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# implementation of the approach
using System;
 
class GFG
{
 
// Function to calculate the prefix sum of the
// rows and the columns of the given matrix
static void prefix_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
    prefix_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




<script>
// Javascript implementation of the approach
 
// Function to calculate the prefix sum of the
// rows and the columns of the given matrix
function prefix_calculate(A, row, col)
{
 
    // Number of rows and cols
    let n = A.length;
    let m = A[0].length;
   
    // First column of the row prefix array
    for (let i = 0; i < n; ++i)
    {
        row[i][0] = A[i][0];
    }
   
    // Update the prefix sum for the rows
    for (let i = 0; i < n; ++i)
    {
        for (let j = 1; j < m; ++j)
        {
            row[i][j] = row[i][j - 1]
                        + A[i][j];
        }
    }
   
    // First row of the column prefix array
    for (let i = 0; i < m; ++i)
    {
        col[0][i] = A[0][i];
    }
   
    // Update the prefix sum for the columns
    for (let i = 0; i < m; ++i)
    {
        for (let 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
function perimeter(i,j,k,row,col,A)
{
    // i and j represent the top left
    // corner of the square and
    // k is the size
    let 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];
   
    let upper_row = row[i][j + k] - row_s;
    let 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];
   
    let lower_row = row[i + k][j + k] - row_s;
    let right_col = col[i + k][j + k] - col_s;
   
    // The perimeter will be
    // sum of all the values
    let 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
function maxPerimeter(A)
{
    // Number of rows and cols
    let n = A.length;
    let m = A[0].length;
   
    let row = new Array(n);
    let col = new Array(n);
     
    for(let i=0;i<n;i++)
    {
        row[i]=new Array(m);
        col[i]=new Array(m);
    }
     
   
    // Function call to calculate
    // the prefix sum of rows and cols
    prefix_calculate(A, row, col);
   
    // To store the maximum perimeter
    let maxPer = 0;
   
    // Nested loops to choose the top-left
    // corner of the square
    for (let i = 0; i < n; ++i)
    {
        for (let j = 0; j < m; ++j)
        {
   
            // Loop for the size of the square
            for (let k = 0; k < Math.min(n - i, m - j); ++k)
            {
   
                // Get the perimeter of the current square
                let perimtr = perimeter(i, j, k,
                                        row, col, A);
   
                // Update the maximum perimeter so far
                maxPer = Math.max(maxPer, perimtr);
            }
        }
    }
   
    return maxPer;
}
 
// Driver code
let A = [[1, 1, 0 ],[1, 1, 1],[0, 1, 1]];
document.write(maxPerimeter(A));
 
// This code is contributed by unknown2108
</script>

Output: 
6

 

Time Complexity: O(N * M * min(N, M))

Auxiliary Space: O(N*M)
 


Article Tags :