🧠
Prefix Sum with Hash Map (Using Transformation)
💡 This approach transforms the problem by converting 0s to -1s and uses prefix sums with a hash map to find the longest subarray efficiently.
Intuition
Replace 0 with -1, then find the longest subarray with sum zero using prefix sums and a hash map to track first occurrences of prefix sums.
Algorithm
- Transform the array: replace 0 with -1.
- Initialize a hash map to store prefix sum indices with sum 0 at index -1.
- Iterate through the array, compute prefix sums.
- If prefix sum seen before, update max length with distance between indices.
- Else, store prefix sum index.
💡 The key insight is that equal prefix sums mean the subarray between them sums to zero, indicating equal 0s and 1s.
def findMaxLength(nums):
for i in range(len(nums)):
if nums[i] == 0:
nums[i] = -1
prefix_sum = 0
seen = {0: -1}
max_length = 0
for i, num in enumerate(nums):
prefix_sum += num
if prefix_sum in seen:
max_length = max(max_length, i - seen[prefix_sum])
else:
seen[prefix_sum] = i
return max_length
# Driver code
if __name__ == '__main__':
print(findMaxLength([0,1,0,1,1,1,0]))
Line Notes
if nums[i] == 0:Transform 0 to -1 to use sum zero logic
seen = {0: -1}Initialize prefix sum map with sum 0 at index -1 for subarrays starting at 0
prefix_sum += numUpdate running prefix sum
if prefix_sum in seen:Check if prefix sum seen before to find balanced subarray
import java.util.*;
public class Solution {
public static int findMaxLength(int[] nums) {
for (int i = 0; i < nums.length; i++) {
if (nums[i] == 0) nums[i] = -1;
}
Map<Integer, Integer> seen = new HashMap<>();
seen.put(0, -1);
int prefixSum = 0, maxLength = 0;
for (int i = 0; i < nums.length; i++) {
prefixSum += nums[i];
if (seen.containsKey(prefixSum)) {
maxLength = Math.max(maxLength, i - seen.get(prefixSum));
} else {
seen.put(prefixSum, i);
}
}
return maxLength;
}
public static void main(String[] args) {
int[] nums = {0,1,0,1,1,1,0};
System.out.println(findMaxLength(nums));
}
}
Line Notes
if (nums[i] == 0) nums[i] = -1;Transform 0 to -1 for sum zero logic
seen.put(0, -1);Prefix sum zero at index -1 to handle subarrays from start
prefixSum += nums[i];Update running prefix sum
if (seen.containsKey(prefixSum))Check if prefix sum seen before to find balanced subarray
#include <iostream>
#include <vector>
#include <unordered_map>
using namespace std;
int findMaxLength(vector<int>& nums) {
for (int& num : nums) {
if (num == 0) num = -1;
}
unordered_map<int, int> seen;
seen[0] = -1;
int prefixSum = 0, maxLength = 0;
for (int i = 0; i < nums.size(); i++) {
prefixSum += nums[i];
if (seen.find(prefixSum) != seen.end()) {
maxLength = max(maxLength, i - seen[prefixSum]);
} else {
seen[prefixSum] = i;
}
}
return maxLength;
}
int main() {
vector<int> nums = {0,1,0,1,1,1,0};
cout << findMaxLength(nums) << endl;
return 0;
}
Line Notes
if (num == 0) num = -1;Transform 0 to -1 for sum zero logic
seen[0] = -1;Initialize prefix sum map with sum 0 at index -1
prefixSum += nums[i];Update running prefix sum
if (seen.find(prefixSum) != seen.end())Check if prefix sum seen before to find balanced subarray
function findMaxLength(nums) {
for (let i = 0; i < nums.length; i++) {
if (nums[i] === 0) nums[i] = -1;
}
const seen = new Map();
seen.set(0, -1);
let prefixSum = 0, maxLength = 0;
for (let i = 0; i < nums.length; i++) {
prefixSum += nums[i];
if (seen.has(prefixSum)) {
maxLength = Math.max(maxLength, i - seen.get(prefixSum));
} else {
seen.set(prefixSum, i);
}
}
return maxLength;
}
// Test
console.log(findMaxLength([0,1,0,1,1,1,0]));
Line Notes
if (nums[i] === 0) nums[i] = -1;Transform 0 to -1 for sum zero logic
seen.set(0, -1);Initialize prefix sum map with sum 0 at index -1
prefixSum += nums[i];Update running prefix sum
if (seen.has(prefixSum))Check if prefix sum seen before to find balanced subarray
Single pass through array with O(1) hash map operations per element.
💡 For n=100000, this means about 100000 operations, which is efficient and scalable.
Interview Verdict: Accepted
This approach is optimal and commonly expected in interviews for this problem.