Prefix Sum of Matrix (Or 2D Array)
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>
Output
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.
Output
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)