Given a matrix (or 2D array) a[][] of integers, find the prefix sum matrix for it. Let prefix sum matrix be psa[][]. The value of psa[i][j] contains the sum of all values which are above it or on the left of it.
Prerequisite: Prefix Sum – 1D
A simple solution is to find psa[i][j] by traversing and adding values from a[0][0] to a[i][j]. Time complexity of this solution is O(R * C * R * C).
An efficient solution is to use previously computed values to compute psa[i][j]. Unlike 1D array prefix sum, this is tricky, here if we simply add psa[i][j-1] and psa[i-1][j], we get sum of elements from a[0][0] to a[i-1][j-1] twice, so we subtract psa[i-1][j-1].
Example :
psa[3][3] = psa[2][3] + psa[3][2] - psa[2][2] + a[3][3] = 6 + 6 - 4 + 1 = 9 The general formula: psa[i][j] = psa[i-1][j] + psa[i][j-1] - psa[i-1][j-1] + a[i][j] Corner Cases (First row and first column) If i = 0 and j = 0 psa[i][j] = a[i][j] If i = 0 and j > 0 psa[i][j] = psa[i][j-1] + a[i][j] If i > 0 and j = 0 psa[i][j] = psa[i-1][j] + a[i][j]
Below is the implementation of the above approach
// C++ Program to find prefix sum of 2d array #include <bits/stdc++.h> using namespace std;
#define R 4 #define C 5 // calculating new array void prefixSum2D( int a[][C])
{ int psa[R][C];
psa[0][0] = a[0][0];
// Filling first row and first column
for ( int i = 1; i < C; i++)
psa[0][i] = psa[0][i - 1] + a[0][i];
for ( int i = 1; i < R; i++)
psa[i][0] = psa[i - 1][0] + a[i][0];
// updating the values in the cells
// as per the general formula
for ( int i = 1; i < R; i++) {
for ( int j = 1; j < C; j++)
// values in the cells of new
// array are updated
psa[i][j] = psa[i - 1][j] + psa[i][j - 1]
- psa[i - 1][j - 1] + a[i][j];
}
// displaying the values of the new array
for ( int i = 0; i < R; i++) {
for ( int j = 0; j < C; j++)
cout << psa[i][j] << " " ;
cout << "\n" ;
}
} // driver code int main()
{ int a[R][C] = { { 1, 1, 1, 1, 1 },
{ 1, 1, 1, 1, 1 },
{ 1, 1, 1, 1, 1 },
{ 1, 1, 1, 1, 1 } };
prefixSum2D(a);
return 0;
} |
// Java program to find prefix sum of 2D array import java.util.*;
class GFG {
// calculating new array
public static void prefixSum2D( int a[][])
{
int R = a.length;
int C = a[ 0 ].length;
int psa[][] = new int [R][C];
psa[ 0 ][ 0 ] = a[ 0 ][ 0 ];
// Filling first row and first column
for ( int i = 1 ; i < C; i++)
psa[ 0 ][i] = psa[ 0 ][i - 1 ] + a[ 0 ][i];
for ( int i = 1 ; i < R; i++)
psa[i][ 0 ] = psa[i - 1 ][ 0 ] + a[i][ 0 ];
// updating the values in the
// cells as per the general formula.
for ( int i = 1 ; i < R; i++)
for ( int j = 1 ; j < C; j++)
// values in the cells of new array
// are updated
psa[i][j] = psa[i - 1 ][j] + psa[i][j - 1 ]
- psa[i - 1 ][j - 1 ] + a[i][j];
for ( int i = 0 ; i < R; i++) {
for ( int j = 0 ; j < C; j++)
System.out.print(psa[i][j] + " " );
System.out.println();
}
}
// driver code
public static void main(String[] args)
{
int a[][] = { { 1 , 1 , 1 , 1 , 1 },
{ 1 , 1 , 1 , 1 , 1 },
{ 1 , 1 , 1 , 1 , 1 },
{ 1 , 1 , 1 , 1 , 1 } };
prefixSum2D(a);
}
} |
# Python Program to find # prefix sum of 2d array R = 4
C = 5
# calculating new array def prefixSum2D(a) :
global C, R
psa = [[ 0 for x in range (C)]
for y in range (R)]
psa[ 0 ][ 0 ] = a[ 0 ][ 0 ]
# Filling first row
# and first column
for i in range ( 1 , C) :
psa[ 0 ][i] = (psa[ 0 ][i - 1 ] + a[ 0 ][i])
for i in range ( 0 , R) :
psa[i][ 0 ] = (psa[i - 1 ][ 0 ] + a[i][ 0 ])
# updating the values in
# the cells as per the
# general formula
for i in range ( 1 , R) :
for j in range ( 1 , C) :
# values in the cells of
# new array are updated
psa[i][j] = (psa[i - 1 ][j] + psa[i][j - 1 ] - psa[i - 1 ][j - 1 ] + a[i][j])
# displaying the values
# of the new array
for i in range ( 0 , R) :
for j in range ( 0 , C) :
print (psa[i][j],
end = " " )
print ()
# Driver Code a = [[ 1 , 1 , 1 , 1 , 1 ],
[ 1 , 1 , 1 , 1 , 1 ],
[ 1 , 1 , 1 , 1 , 1 ],
[ 1 , 1 , 1 , 1 , 1 ]]
prefixSum2D(a) # This code is contributed by # Manish Shaw(manishshaw1) |
// C# program to find prefix // sum of 2D array using System;
class GFG
{ // calculating new array
static void prefixSum2D( int [,]a)
{
int R = a.GetLength(0);
int C = a.GetLength(1);
int [,]psa = new int [R, C];
psa[0, 0] = a[0, 0];
// Filling first row
// and first column
for ( int i = 1; i < C; i++)
psa[0, i] = psa[0, i - 1] +
a[0, i];
for ( int i = 1; i < R; i++)
psa[i, 0] = psa[i - 1, 0] +
a[i, 0];
// updating the values in the
// cells as per the general formula.
for ( int i = 1; i < R; i++)
for ( int j = 1; j < C; j++)
// values in the cells of
// new array are updated
psa[i, j] = psa[i - 1, j] +
psa[i, j - 1] -
psa[i - 1, j - 1] +
a[i, j];
for ( int i = 0; i < R; i++)
{
for ( int j = 0; j < C; j++)
Console.Write(psa[i, j] + " " );
Console.WriteLine();
}
}
// Driver Code
static void Main()
{
int [,]a = new int [,]{{1, 1, 1, 1, 1},
{1, 1, 1, 1, 1},
{1, 1, 1, 1, 1},
{1, 1, 1, 1, 1}};
prefixSum2D(a);
}
} // This code is contributed by manishshaw1 |
<?php // PHP Program to find // prefix sum of 2d array $R = 4;
$C = 5;
// calculating new array function prefixSum2D( $a )
{ global $C , $R ;
$psa = array ();
$psa [0][0] = $a [0][0];
// Filling first row
// and first column
for ( $i = 1; $i < $C ; $i ++)
$psa [0][ $i ] = $psa [0][ $i - 1] +
$a [0][ $i ];
for ( $i = 0; $i < $R ; $i ++)
$psa [ $i ][0] = $psa [ $i - 1][0] +
$a [ $i ][0];
// updating the values in
// the cells as per the
// general formula
for ( $i = 1; $i < $R ; $i ++)
{
for ( $j = 1; $j < $C ; $j ++)
// values in the cells of
// new array are updated
$psa [ $i ][ $j ] = $psa [ $i - 1][ $j ] +
$psa [ $i ][ $j - 1] -
$psa [ $i - 1][ $j - 1] +
$a [ $i ][ $j ];
}
// displaying the values
// of the new array
for ( $i = 0; $i < $R ; $i ++)
{
for ( $j = 0; $j < $C ; $j ++)
echo ( $psa [ $i ][ $j ]. " " );
echo ( "\n" );
}
} // Driver Code $a = array ( array ( 1, 1, 1, 1, 1 ),
array ( 1, 1, 1, 1, 1 ),
array ( 1, 1, 1, 1, 1 ),
array ( 1, 1, 1, 1, 1 ));
prefixSum2D( $a );
// This code is contributed by // Manish Shaw(manishshaw1) ?> |
<script> // Javascript program to find prefix sum of 2D array // calculating new array function prefixSum2D(a)
{ let R = a.length;
let C = a[0].length;
let psa = new Array(R);
for (let i = 0; i < R; i++)
{
psa[i] = new Array(C);
for (let j = 0; j < C; j++)
psa[i][j] = 0;
}
psa[0][0] = a[0][0];
// Filling first row and first column
for (let i = 1; i < C; i++)
psa[0][i] = psa[0][i - 1] + a[0][i];
for (let i = 1; i < R; i++)
psa[i][0] = psa[i - 1][0] + a[i][0];
// updating the values in the
// cells as per the general formula.
for (let i = 1; i < R; i++)
for (let j = 1; j < C; j++)
// values in the cells of new array
// are updated
psa[i][j] = psa[i - 1][j] + psa[i][j - 1]
- psa[i - 1][j - 1] + a[i][j];
for (let i = 0; i < R; i++) {
for (let j = 0; j < C; j++)
document.write(psa[i][j] + " " );
document.write( "<br>" );
}
} // driver code let a=[[ 1, 1, 1, 1, 1 ], [ 1, 1, 1, 1, 1 ],
[ 1, 1, 1, 1, 1 ],
[ 1, 1, 1, 1, 1 ]];
prefixSum2D(a); // This code is contributed by avanitrachhadiya2155 </script> |
1 2 3 4 5 2 4 6 8 10 3 6 9 12 15 4 8 12 16 20
Time Complexity: O(R*C)
Auxiliary Space: O(R*C)
Another Efficient solution in which we also use the previously calculated sums in two main steps would be:
- Calculate the vertical prefix sum for each column.
- Calculate the horizontal prefix sum for each row.
Example
// c = the number of columns // r = the number of rows // a is the matrix // calculating the vertical sum for each column in the Matrix for(column = 0 to column = c-1) for(row = 1 to row = r-1) a[row][column] += a[row-1][column]; // calculating the horizontal sum for each row in the Matrix for(row = 0 to row = r-1) for(column = 1 to column = c-1) a[row][column] += a[row][column -1];
Below is the Implementation of the above approach
#include <iostream> #include <iomanip> using namespace std;
void prefixSum( int arr[3][3], int n);
void print( int arr[3][3], int n);
int main()
{ int n = 3;
int arr[3][3] = {{10,20,30},
{5, 10, 20},
{2, 4, 6}
};
prefixSum(arr, n);
print(arr, n);
} void prefixSum( int arr[3][3], int n) {
//vertical prefixsum
for ( int j = 0; j < n; j++) {
for ( int i = 1; i < n; i++) {
arr[i][j] += arr[i-1][j];
}
}
//horizontal prefixsum
for ( int i = 0; i < n; i++) {
for ( int j = 1; j < n; j++) {
arr[i][j] += arr[i][j-1];
}
}
} void print( int arr[3][3], int n) {
for ( int i = 0; i < n; i++) {
for ( int j = 0; j < n; j++) {
cout << setw(3) << left << arr[i][j] << " " ;
}
cout << '\n' ;
}
} |
import java.io.*;
import java.lang.*;
import java.util.*;
public class GFG {
public static void main(String[] args)
{
int n = 3 ;
int arr[][] = new int [][] { { 10 , 20 , 30 },
{ 5 , 10 , 20 },
{ 2 , 4 , 6 } };
prefixSum(arr, n);
print(arr, n);
}
static void prefixSum( int arr[][], int n)
{
// vertical prefixsum
for ( int j = 0 ; j < n; j++) {
for ( int i = 1 ; i < n; i++) {
arr[i][j] += arr[i - 1 ][j];
}
}
// horizontal prefixsum
for ( int i = 0 ; i < n; i++) {
for ( int j = 1 ; j < n; j++) {
arr[i][j] += arr[i][j - 1 ];
}
}
}
static void print( int arr[][], int n)
{
for ( int i = 0 ; i < n; i++) {
for ( int j = 0 ; j < n; j++) {
System.out.print(arr[i][j] + " " );
}
System.out.println();
}
}
} // This code is contributed by ishankhandelwals. |
def prefixsum(arr, n):
# vertical prefixsum
for j in range (n):
for i in range ( 1 , n):
arr[i][j] + = arr[i - 1 ][j]
# horizontal prefixsum
for i in range (n):
for j in range ( 1 , n):
arr[i][j] + = arr[i][j - 1 ]
def printarr(arr, n):
for i in range (n):
for j in range (n):
print (arr[i][j], end = " " )
print ()
# Driver Code n = 3
arr = [[ 10 , 20 , 30 ],[ 5 , 10 , 20 ],[ 2 , 4 , 6 ]]
prefixsum(arr,n) printarr(arr,n) # This code is contributed by # Vibhu Karnwal |
// C# code for above approach using System;
public class gfg
{ public static void prefixSum( int [,] arr, int n){
for ( int j = 0; j < n; j++) {
for ( int i = 1; i < n; i++) {
arr[i,j] += arr[i-1,j];
}
}
//horizontal prefixsum
for ( int i = 0; i < n; i++) {
for ( int j = 1; j < n; j++) {
arr[i,j] += arr[i,j-1];
}
}
}
public static void print( int [,] arr, int n){
for ( int i = 0; i < n; i++) {
for ( int j = 0; j < n; j++) {
Console.Write( "{0} " ,arr[i,j]);
}
Console.WriteLine();
}
}
public static void Main( string [] args)
{
int n = 3;
int [ , ] arr = new int [3,3] {{10,20,30},
{5, 10, 20},
{2, 4, 6}
} ;
prefixSum(arr, n);
print(arr, n);
}
} // This code is contributed by ishankhandelwals. |
// Js code for above approach function prefixSum(arr, n) {
//vertical prefixsum
for (let j = 0; j < n; j++) {
for (let i = 1; i < n; i++) {
arr[i][j] += arr[i - 1][j];
}
}
//horizontal prefixsum
for (let i = 0; i < n; i++) {
for (let j = 1; j < n; j++) {
arr[i][j] += arr[i][j - 1];
}
}
} function print(arr, n) {
for (let i = 0; i < n; i++) {
for (let j = 0; j < n; j++) {
console.log(arr[i][j]);
}
}
} let n = 3; let arr= [[ 10, 20, 30 ], [5, 10, 20 ],
[ 2, 4, 6 ]];
prefixSum(arr, n); print(arr, n); // This code is contributed by ishankhandelwals. |
10 30 60 15 45 95 17 51 107
Time Complexity: O(R*C), where R and C are the Rows and Columns of the given matrix respectively.
Auxiliary Space: O(R*C)