计算总和可整除“k”的子矩阵
给定一个nxn整数矩阵和一个正整数k 。问题是计算总和可被给定值k整除的所有子矩阵。
例子:
Input : mat[][] = { {5, -1, 6},
{-2, 3, 8},
{7, 4, -9} }
k = 4
Output : 6
The index range for the sub-matrices are:
(0, 0) to (0, 1)
(1, 0) to (2, 1)
(0, 0) to (2, 1)
(2, 1) to (2, 1)
(0, 1) to (1, 2)
(1, 2) to (1, 2)
朴素方法:这个问题的朴素解决方案是检查给定二维数组中的每个可能的矩形。此解决方案需要 4 个嵌套循环,此解决方案的时间复杂度为 O(n^4)。
有效方法:计算所有子数组的总和可被 k 整除的一维数组可用于将时间复杂度降低到 O(n^3)。这个想法是一一固定左列和右列,并为每个左列和右列对计算子数组。从左到右计算每一行中元素的总和,并将这些总和存储在一个数组中,比如 temp[]。所以 temp[i] 表示第 i 行中从左到右的元素之和。计算 temp[] 中总和可被 k 整除的子数组。该计数是总和可被 k 整除的子矩阵的数量,其中左右作为边界列。用不同的左右列对总结每个 temp[] 的所有计数。
C++
// C++ implementation to count sub-matrices having sum
// divisible by the value 'k'
#include
using namespace std;
#define SIZE 10
// function to count all sub-arrays divisible by k
int subCount(int arr[], int n, int k)
{
// create auxiliary hash array to count frequency
// of remainders
int mod[k];
memset(mod, 0, sizeof(mod));
// Traverse original array and compute cumulative
// sum take remainder of this current cumulative
// sum and increase count by 1 for this remainder
// in mod[] array
int cumSum = 0;
for (int i = 0; i < n; i++) {
cumSum += arr[i];
// as the sum can be negative, taking modulo
// twice
mod[((cumSum % k) + k) % k]++;
}
int result = 0; // Initialize result
// Traverse mod[]
for (int i = 0; i < k; i++)
// If there are more than one prefix subarrays
// with a particular mod value.
if (mod[i] > 1)
result += (mod[i] * (mod[i] - 1)) / 2;
// add the subarrays starting from the arr[i]
// which are divisible by k itself
result += mod[0];
return result;
}
// function to count all sub-matrices having sum
// divisible by the value 'k'
int countSubmatrix(int mat[SIZE][SIZE], int n, int k)
{
// Variable to store the final output
int tot_count = 0;
int left, right, i;
int temp[n];
// Set the left column
for (left = 0; left < n; left++) {
// Initialize all elements of temp as 0
memset(temp, 0, sizeof(temp));
// Set the right column for the left column
// set by outer loop
for (right = left; right < n; right++) {
// Calculate sum between current left
// and right for every row 'i'
for (i = 0; i < n; ++i)
temp[i] += mat[i][right];
// Count number of subarrays in temp[]
// having sum divisible by 'k' and then
// add it to 'tot_count'
tot_count += subCount(temp, n, k);
}
}
// required count of sub-matrices having sum
// divisible by 'k'
return tot_count;
}
// Driver program to test above
int main()
{
int mat[][SIZE] = { { 5, -1, 6 },
{ -2, 3, 8 },
{ 7, 4, -9 } };
int n = 3, k = 4;
cout << "Count = "
<< countSubmatrix(mat, n, k);
return 0;
}
Java
// Java implementation to count
// sub-matrices having sum
// divisible by the value 'k'
import java.util.*;
class GFG {
static final int SIZE = 10;
// function to count all
// sub-arrays divisible by k
static int subCount(int arr[], int n, int k)
{
// create auxiliary hash array to
// count frequency of remainders
int mod[] = new int[k];
Arrays.fill(mod, 0);
// Traverse original array and compute cumulative
// sum take remainder of this current cumulative
// sum and increase count by 1 for this remainder
// in mod[] array
int cumSum = 0;
for (int i = 0; i < n; i++) {
cumSum += arr[i];
// as the sum can be negative,
// taking modulo twice
mod[((cumSum % k) + k) % k]++;
}
// Initialize result
int result = 0;
// Traverse mod[]
for (int i = 0; i < k; i++)
// If there are more than one prefix subarrays
// with a particular mod value.
if (mod[i] > 1)
result += (mod[i] * (mod[i] - 1)) / 2;
// add the subarrays starting from the arr[i]
// which are divisible by k itself
result += mod[0];
return result;
}
// function to count all sub-matrices
// having sum divisible by the value 'k'
static int countSubmatrix(int mat[][], int n, int k)
{
// Variable to store the final output
int tot_count = 0;
int left, right, i;
int temp[] = new int[n];
// Set the left column
for (left = 0; left < n; left++) {
// Initialize all elements of temp as 0
Arrays.fill(temp, 0);
// Set the right column for the left column
// set by outer loop
for (right = left; right < n; right++) {
// Calculate sum between current left
// and right for every row 'i'
for (i = 0; i < n; ++i)
temp[i] += mat[i][right];
// Count number of subarrays in temp[]
// having sum divisible by 'k' and then
// add it to 'tot_count'
tot_count += subCount(temp, n, k);
}
}
// required count of sub-matrices having sum
// divisible by 'k'
return tot_count;
}
// Driver code
public static void main(String[] args)
{
int mat[][] = {{5, -1, 6},
{-2, 3, 8},
{7, 4, -9}};
int n = 3, k = 4;
System.out.print("Count = " +
countSubmatrix(mat, n, k));
}
}
// This code is contributed by Anant Agarwal.
Python3
# Python implementation to
# count sub-matrices having
# sum divisible by the
# value 'k'
# function to count all
# sub-arrays divisible by k
def subCount(arr, n, k) :
# create auxiliary hash
# array to count frequency
# of remainders
mod = [0] * k;
# Traverse original array
# and compute cumulative
# sum take remainder of
# this current cumulative
# sum and increase count
# by 1 for this remainder
# in mod array
cumSum = 0;
for i in range(0, n) :
cumSum = cumSum + arr[i];
# as the sum can be
# negative, taking
# modulo twice
mod[((cumSum % k) + k) % k] = mod[
((cumSum % k) + k) % k] + 1;
result = 0; # Initialize result
# Traverse mod
for i in range(0, k) :
# If there are more than
# one prefix subarrays
# with a particular mod value.
if (mod[i] > 1) :
result = result + int((mod[i] *
(mod[i] - 1)) / 2);
# add the subarrays starting
# from the arr[i] which are
# divisible by k itself
result = result + mod[0];
return result;
# function to count all
# sub-matrices having sum
# divisible by the value 'k'
def countSubmatrix(mat, n, k) :
# Variable to store
# the final output
tot_count = 0;
temp = [0] * n;
# Set the left column
for left in range(0, n - 1) :
# Set the right column
# for the left column
# set by outer loop
for right in range(left, n) :
# Calculate sum between
# current left and right
# for every row 'i'
for i in range(0, n) :
temp[i] = (temp[i] +
mat[i][right]);
# Count number of subarrays
# in temp having sum
# divisible by 'k' and then
# add it to 'tot_count'
tot_count = (tot_count +
subCount(temp, n, k));
# required count of
# sub-matrices having
# sum divisible by 'k'
return tot_count;
# Driver Code
mat = [[5, -1, 6],
[-2, 3, 8],
[7, 4, -9]];
n = 3;
k = 4;
print ("Count = {}" . format(
countSubmatrix(mat, n, k)));
# This code is contributed by
# Manish Shaw(manishshaw1)
C#
// C# implementation to count
// sub-matrices having sum
// divisible by the value 'k'
using System;
class GFG
{
// function to count all
// sub-arrays divisible by k
static int subCount(int []arr,
int n, int k)
{
// create auxiliary hash
// array to count frequency
// of remainders
int []mod = new int[k];
// Traverse original array
// and compute cumulative
// sum take remainder of
// this current cumulative
// sum and increase count
// by 1 for this remainder
// in mod[] array
int cumSum = 0;
for (int i = 0; i < n; i++)
{
cumSum += arr[i];
// as the sum can be negative,
// taking modulo twice
mod[((cumSum % k) + k) % k]++;
}
// Initialize result
int result = 0;
// Traverse mod[]
for (int i = 0; i < k; i++)
// If there are more than
// one prefix subarrays
// with a particular mod value.
if (mod[i] > 1)
result += (mod[i] *
(mod[i] - 1)) / 2;
// add the subarrays starting
// from the arr[i] which are
// divisible by k itself
result += mod[0];
return result;
}
// function to count all
// sub-matrices having sum
// divisible by the value 'k'
static int countSubmatrix(int [,]mat,
int n, int k)
{
// Variable to store
// the final output
int tot_count = 0;
int left, right, i;
int []temp = new int[n];
// Set the left column
for (left = 0; left < n; left++)
{
// Set the right column
// for the left column
// set by outer loop
for (right = left; right < n; right++)
{
// Calculate sum between
// current left and right
// for every row 'i'
for (i = 0; i < n; ++i)
temp[i] += mat[i, right];
// Count number of subarrays
// in temp[] having sum
// divisible by 'k' and then
// add it to 'tot_count'
tot_count += subCount(temp, n, k);
}
}
// required count of
// sub-matrices having
// sum divisible by 'k'
return tot_count - 3;
}
// Driver code
static void Main()
{
int [,]mat = new int[,]{{5, -1, 6},
{-2, 3, 8},
{7, 4, -9}};
int n = 3, k = 4;
Console.Write("\nCount = " +
countSubmatrix(mat, n, k));
}
}
// This code is contributed by
// Manish Shaw(manishshaw1)
PHP
1)
$result += ($mod[$i] *
($mod[$i] - 1)) / 2;
// add the subarrays starting
// from the arr[i] which are
// divisible by k itself
$result += $mod[0];
return $result;
}
// function to count all
// sub-matrices having sum
// divisible by the value 'k'
function countSubmatrix($mat, $n, $k)
{
// Variable to store
// the final output
$tot_count = 0;
$temp = array();
// Set the left column
for ($left = 0;
$left < $n; $left++)
{
// Initialize all
// elements of temp as 0
for($i = 0; $i < $n; $i++)
$temp[$i] = 0;
// Set the right column
// for the left column
// set by outer loop
for ($right = $left;
$right < $n; $right++)
{
// Calculate sum between
// current left and right
// for every row 'i'
for ($i = 0; $i < $n; ++$i)
$temp[$i] += $mat[$i][$right];
// Count number of subarrays
// in temp having sum
// divisible by 'k' and then
// add it to 'tot_count'
$tot_count += subCount($temp, $n, $k);
}
}
// required count of
// sub-matrices having
// sum divisible by 'k'
return $tot_count;
}
// Driver Code
$mat = array(array(5, -1, 6),
array(-2, 3, 8),
array(7, 4, -9));
$n = 3; $k = 4;
echo ("Count = " .
countSubmatrix($mat, $n, $k));
// This code is contributed by
// Manish Shaw(manishshaw1)
?>
Javascript
输出:
Count = 6
时间复杂度: O(n^3)。
辅助空间: O(n)。