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: 6

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:

filter_none

edit
close

play_arrow

link
brightness_4
code

// C++ implementation of the approach
#include <bits/stdc++.h>
using namespace std;
  
// Function to calculate the perfix sum of the
// rows and the columns of the given matrix
void perfix_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
    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<vector<int> > A = {
        { 1, 1, 0 },
        { 1, 1, 1 },
        { 0, 1, 1 }
    };
  
    cout << maxPerimeter(A);
  
    return 0;
}
chevron_right

filter_none

edit
close

play_arrow

link
brightness_4
code

// 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
chevron_right

filter_none

edit
close

play_arrow

link
brightness_4
code

# 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
chevron_right

filter_none

edit
close

play_arrow

link
brightness_4
code

// 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
chevron_right

Output:
6

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

Attention reader! Don’t stop learning now. Get hold of all the important DSA concepts with the DSA Self Paced Course at a student-friendly price and become industry ready.





Check out this Author's contributed articles.

If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.



Article Tags :