1074 - Number of Submatrices That Sum to Target
Difficulty: Hard | Pattern: Prefix Sum + Hash Map (2D Subarray Sum) | Company tags: Amazon, Google
Problem Statement
Given a matrix and a target, return the number of non-empty submatrices that sum to target.
A submatrix x1, y1, x2, y2 is the set of all cells matrix[x][y] with x1 <= x <= x2 and y1 <= y <= y2.
Example 1:
Input: matrix = [[0,1,0],[1,1,1],[0,1,0]], target = 0
Output: 4
Example 2:
Input: matrix = [[1,-1],[-1,1]], target = 0
Output: 5
Approach: 2D Prefix Sum + 1D Subarray Sum — O(m² × n)
Key insight: Reduce to the 1D problem "count subarrays with sum = target" (LeetCode 560). Fix two row bounds r1 and r2. Compute the column sums between these rows. Then use the 1D hash-map approach on this column-sum array.
Algorithm Flow
from collections import defaultdict
def numSubmatrixSumTarget(matrix: list[list[int]], target: int) -> int:
m, n = len(matrix), len(matrix[0])
# Compute row prefix sums (in-place)
for row in matrix:
for j in range(1, n):
row[j] += row[j-1]
count = 0
for r1 in range(m):
col_sum = [0] * n
for r2 in range(r1, m):
for c in range(n):
col_sum[c] += matrix[r2][c]
# Count subarrays in col_sum that equal target
prefix_count = defaultdict(int)
prefix_count[0] = 1
running = 0
for s in col_sum:
running += s
count += prefix_count[running - target]
prefix_count[running] += 1
return count
Algorithm Breakdown
- Row prefix sums:
matrix[r][c]becomes sum of rowrfrom column 0 to c. - Fix rows r1, r2:
col_sum[c]= sum of rectangle from(r1,0)to(r2,c)minus sum to left. - 1D scan: For each pair
(r1, r2), count column-ranges with sum = target using theprefix_sum - targethash map trick.
Complexity
- Time: O(m² × n) — O(m²) row pairs × O(n) 1D scan each
- Space: O(n) for col_sum + O(n) for prefix_count hash map
This is the 2D generalization of LeetCode 560 (Subarray Sum Equals K) — understanding 560 first makes this problem much clearer.
Key Terms
| Term | Definition |
|---|---|
| Prefix sum | Running total up to an index, letting range sums be computed in O(1) via subtraction. |
| 2D reduction | Collapsing a matrix range problem into repeated 1D subarray problems by fixing row bounds. |
| Hash map counting | Storing frequency of each prefix-sum value seen so far to count matching subarrays in O(1) lookup. |
| Row pair (r1, r2) | The two row boundaries that define the vertical extent of every candidate submatrix. |
| Complementary sum | The value running - target looked up in the hash map to count valid subarrays ending at the current position. |
FAQ
Q: Can this be solved without extra space? A: Not efficiently — the O(m²·n²) brute force checks every submatrix directly without a hash map, but the O(m²·n) approach requires the prefix_count hash map to avoid a third nested loop.
Q: What if the matrix contains only non-negative numbers? A: The hash-map approach still applies, but a sliding-window technique could also work per row-pair since sums only increase — though the hash-map solution already handles negatives, so it's simpler to keep one general approach.
Q: How would this change if we wanted the largest submatrix (not count) summing to at most K? A: That becomes LeetCode 363 (Max Sum of Rectangle No Larger Than K), which uses the same row-pair reduction but a sorted-set/binary-search lookup instead of exact hash-map counting.
Q: What is the time complexity trade-off vs brute force? A: Brute force is O(m²n²) (all submatrix corners); this approach is O(m²n) by reducing the inner two dimensions to a single O(n) hash-map pass per row pair.
Q: What if target is 0 and the matrix has many zero cells?
A: Every all-zero submatrix counts, and the empty-prefix prefix_count[0] = 1 seed correctly counts subarrays that sum to target starting from index 0.
Quick Revision
- Goal: count submatrices whose sum equals
target. - Step 1: convert each row into a running row-prefix-sum so any horizontal range sum is O(1).
- Step 2: fix row bounds
r1, r2; buildcol_sum[c]= sum of columncbetween those rows. - Step 3: run the classic "subarray sum equals k" hash-map scan on
col_sum. - Seed
prefix_count = {0: 1}to handle subarrays starting at index 0. - For each running sum, add
prefix_count[running - target]to the answer, then recordrunning. - Outer loop over
r1, inner loop overr2gives O(m²) row-pair combinations. - Total complexity: O(m²·n) time, O(n) space.
- This is the 2D generalization of LeetCode 560 (Subarray Sum Equals K) — master 560 first.
Related Problems
- 304 - Range Sum Query 2D - Immutable — same 2D prefix-sum construction
- 363 - Max Sum of Rectangle No Larger Than K — same row-pair reduction with a different inner query
- Subarray Sum Equals K (LeetCode 560) — the 1D hash-map pattern this problem builds on (no file in this set)