给定整数矩阵mat [] [] ,其大小为N * M。任务是找到矩阵中正方形的最大周长。正方形的周长定义为位于正方形侧面上的所有值的总和。
例子:
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
天真的方法:一种简单的解决方案是在给定的矩阵mat [] []内生成所有可能的正方形,然后找到其周长并从中取最大值。
高效的方法:
- 为了找到正方形的周长,应该知道边的长度。
- 在这里,长度被描述为该特定行和列上元素的总和。
- 将创建两个大小为N * M的矩阵,这些矩阵将存储原始矩阵的行的前缀和与列的前缀和,以便可以在恒定时间内计算边的长度。
- 将有两个嵌套循环,一个从1到N ,另一个从1到M,以找到正方形的左角(左上角),并且一个循环将是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
输出:
6
时间复杂度: O(N * M * min(N,M))