[Naive Approach] Using four Nested Loops - O(n^4) Time and O(n^2) Space
The naive solution for this problem is to check the sum of every possible rectangle in given 2D array. For this we can use four nested loop to fix the upper row, bottom row, left column and right column of the sub matrix. Now for each such sub matrix we can find its sum using a 2D prefix sum matrix in constant time. If this calculated sum is equal to 0 then update the maximum area found.
[Expected Approach] Using Prefix Sum - O(n^3) Time and O(n) Space
The idea is to iterate over all pairs of rows to fix the top and bottom boundaries (height) of the zero-sum submatrix. Then, for each pair, we find the maximum width such that the total sum of the submatrix is zero.
To find the width of largest submatrix with zero sum for a given top and bottom row pair:
For a given top-bottom pair, we compute the column-wise cumulative sum in a temporary array temp[].
The Length of longest subarray with 0 Sum in temp[] array will also be the width of the largest 0-sum submatrix.
C++
//Driver Code Starts#include<iostream>#include<vector>#include<unordered_map>usingnamespacestd;//Driver Code EndsintmaxZeroSumSubarray(vector<int>&arr){intprefSum=0;intmaxLength=0;// Hash map to store the first// index of each prefix sum.unordered_map<int,int>mp;// Iterate through the array to// find subarrays with zero sum.for(inti=0;i<arr.size();i++){prefSum+=arr[i];if(prefSum==0)maxLength=i+1;if(mp.find(prefSum)!=mp.end()){// If this prefSum repeats,// find subarray length.maxLength=max(maxLength,(i-mp[prefSum]));}else{// Only store the index of the// first occurrence of prefSum.mp[prefSum]=i;}}returnmaxLength;}intzeroSumSubmat(vector<vector<int>>&mat){introws=mat.size();intcols=mat[0].size();intmaxArea=0;for(inti=0;i<rows;i++){// Temporary array to store// the column-wise cumulative sum.vector<int>temp(cols,0);// Iterate over each row from i to jfor(intj=i;j<rows;j++){// Accumulate the column-wise// sum for rows between i and j.for(intk=0;k<cols;k++)temp[k]+=mat[j][k];// Find the longest zero-sum// subarray in column sums.intlen=maxZeroSumSubarray(temp);// Update the maximum areaintcurHeight=(j-i+1);maxArea=max(maxArea,curHeight*len);}}returnmaxArea;}//Driver Code Startsintmain(){vector<vector<int>>mat={{9,7,16,5},{1,-6,-7,3},{1,8,7,9},{7,-2,0,10}};cout<<zeroSumSubmat(mat)<<endl;return0;}//Driver Code Ends
Java
//Driver Code Startsimportjava.util.HashMap;//Driver Code EndsclassGfG{staticintmaxZeroSumSubarray(int[]arr){intprefSum=0;intmaxLength=0;// Hash map to store the first// index of each prefix sum.HashMap<Integer,Integer>mp=newHashMap<>();// Iterate through the array to// find subarrays with zero sum.for(inti=0;i<arr.length;i++){prefSum+=arr[i];if(prefSum==0)maxLength=i+1;if(mp.containsKey(prefSum)){// If this prefSum repeats,// find subarray length.maxLength=Math.max(maxLength,(i-mp.get(prefSum)));}else{// Only store the index of the// first occurrence of prefSum.mp.put(prefSum,i);}}returnmaxLength;}staticintzeroSumSubmat(int[][]mat){introws=mat.length;intcols=mat[0].length;intmaxArea=0;for(inti=0;i<rows;i++){// Temporary array to store// the column-wise cumulative sum.int[]temp=newint[cols];// Iterate over each row from i to jfor(intj=i;j<rows;j++){// Accumulate the column-wise// sum for rows between i and j.for(intk=0;k<cols;k++)temp[k]+=mat[j][k];// Find the longest zero-sum// subarray in column sums.intlen=maxZeroSumSubarray(temp);// Update the maximum areaintcurHeight=(j-i+1);maxArea=Math.max(maxArea,curHeight*len);}}returnmaxArea;}//Driver Code Startspublicstaticvoidmain(String[]args){int[][]mat={{9,7,16,5},{1,-6,-7,3},{1,8,7,9},{7,-2,0,10}};System.out.println(zeroSumSubmat(mat));}}//Driver Code Ends
Python
defmaxZeroSumSubarray(arr):prefSum=0maxLength=0# Hash map to store the first# index of each prefix sum.mp={}# Iterate through the array to# find subarrays with zero sum.foriinrange(len(arr)):prefSum+=arr[i]ifprefSum==0:maxLength=i+1ifprefSuminmp:# If this prefSum repeats,# find subarray length.maxLength=max(maxLength,(i-mp[prefSum]))else:# Only store the index of the# first occurrence of prefSum.mp[prefSum]=ireturnmaxLengthdefzeroSumSubmat(mat):rows=len(mat)cols=len(mat[0])maxArea=0foriinrange(rows):# Temporary array to store# the column-wise cumulative sum.temp=[0]*cols# Iterate over each row from i to jforjinrange(i,rows):# Accumulate the column-wise# sum for rows between i and j.forkinrange(cols):temp[k]+=mat[j][k]# Find the longest zero-sum# subarray in column sums.len_sub=maxZeroSumSubarray(temp)# Update the maximum areacurHeight=(j-i+1)maxArea=max(maxArea,curHeight*len_sub)returnmaxAreaif__name__=='__main__':mat=[[9,7,16,5],[1,-6,-7,3],[1,8,7,9],[7,-2,0,10]]print(zeroSumSubmat(mat))
C#
//Driver Code StartsusingSystem;usingSystem.Collections.Generic;//Driver Code EndsclassGfG{staticintMaxZeroSumSubarray(int[]arr){intprefSum=0;intmaxLength=0;// Hash map to store the first// index of each prefix sum.Dictionary<int,int>mp=newDictionary<int,int>();// Iterate through the array to// find subarrays with zero sum.for(inti=0;i<arr.Length;i++){prefSum+=arr[i];if(prefSum==0)maxLength=i+1;if(mp.ContainsKey(prefSum)){// If this prefSum repeats,// find subarray length.maxLength=Math.Max(maxLength,(i-mp[prefSum]));}else{// Only store the index of the// first occurrence of prefSum.mp[prefSum]=i;}}returnmaxLength;}staticintZeroSumSubmat(int[,]mat){introws=mat.GetLength(0);intcols=mat.GetLength(1);intmaxArea=0;for(inti=0;i<rows;i++){// Temporary array to store// the column-wise cumulative sum.int[]temp=newint[cols];// Iterate over each row from i to jfor(intj=i;j<rows;j++){// Accumulate the column-wise// sum for rows between i and j.for(intk=0;k<cols;k++)temp[k]+=mat[j,k];// Find the longest zero-sum// subarray in column sums.intlen=MaxZeroSumSubarray(temp);// Update the maximum areaintcurHeight=(j-i+1);maxArea=Math.Max(maxArea,curHeight*len);}}returnmaxArea;}//Driver Code StartsstaticvoidMain(){int[,]mat={{9,7,16,5},{1,-6,-7,3},{1,8,7,9},{7,-2,0,10}};Console.WriteLine(ZeroSumSubmat(mat));}}//Driver Code Ends
JavaScript
functionmaxZeroSumSubarray(arr){letprefSum=0;letmaxLength=0;// Hash map to store the first// index of each prefix sum.letmp=newMap();// Iterate through the array to// find subarrays with zero sum.for(leti=0;i<arr.length;i++){prefSum+=arr[i];if(prefSum===0)maxLength=i+1;if(mp.has(prefSum)){// If this prefSum repeats,// find subarray length.maxLength=Math.max(maxLength,(i-mp.get(prefSum)));}else{// Only store the index of the// first occurrence of prefSum.mp.set(prefSum,i);}}returnmaxLength;}functionzeroSumSubmat(mat){letrows=mat.length;letcols=mat[0].length;letmaxArea=0;for(leti=0;i<rows;i++){// Temporary array to store// the column-wise cumulative sum.lettemp=newArray(cols).fill(0);// Iterate over each row from i to jfor(letj=i;j<rows;j++){// Accumulate the column-wise// sum for rows between i and j.for(letk=0;k<cols;k++)temp[k]+=mat[j][k];// Find the longest zero-sum// subarray in column sums.letlen=maxZeroSumSubarray(temp);// Update the maximum arealetcurHeight=(j-i+1);maxArea=Math.max(maxArea,curHeight*len);}}returnmaxArea;}// Driver codeletmat=[[9,7,16,5],[1,-6,-7,3],[1,8,7,9],[7,-2,0,10]];console.log(zeroSumSubmat(mat));