You've mastered sliding window on 1D arrays. You can solve "longest substring" problems in your sleep. Then you see: "Find the maximum sum of a submatrix of size ."
And suddenly, you're lost. Do you slide in both dimensions? How do you track state efficiently? Can you even use sliding window here?
The answer is yes, but with a twist. 2D sliding window requires rethinking the pattern—you can't just add another loop. In this guide, I'll show you how to extend sliding window to matrices without falling into the complexity traps.
You'll learn:
- Why 2D sliding window is fundamentally harder
- The most common 2D problem types you'll encounter
- The dimension compression technique that reduces 2D to 1D
- A generalized approach with working code
- Common pitfalls and how to avoid them
By the end, you'll handle matrix problems with confidence instead of panic.
TL;DR — 2D Sliding Window Essentials
- Never enumerate all rectangles: That's — too slow
- Core technique: Fix two row boundaries, compress columns to 1D array, apply 1D sliding window
- Fixed-size problems: Use 2D prefix sums for queries after preprocessing
- Variable-size problems: Fix rows
[r1, r2], compress columns, run Kadane's or 1D window - Complexity: for most variable-size problems
- Common pitfall: Forgetting to reset
col_sumswhen moving to newr1 - Prerequisites: Master 1D sliding window first (15-20 problems)
Why 2D Sliding Window is Harder
In 1D, sliding window is intuitive: expand right, shrink left, track a single range. In 2D, everything gets more complex.
Two Dimensions, Compressing One Dimension
The Challenge: In a 2D matrix, a "window" is now a rectangular region defined by:
- Top row and bottom row
- Left column and right column
That's four boundaries to manage instead of two. Naively, you might think:
# WRONG: Trying to slide in both dimensions simultaneously
for top in range(rows):
for bottom in range(top, rows):
for left in range(cols):
for right in range(left, cols):
# This is O(R^2 * C^2) - way too slow!This brute force approach works, but it's . For a matrix, that's 100 million operations—too slow for most interview constraints.
The Key Insight: You fix two boundaries (usually the rows) and apply 1D sliding window on the compressed columns.
Higher Complexity, Pointer Logic
Even with compression, you're dealing with:
- Nested loops for fixing boundaries
- Column-wise accumulation
- State management across row iterations
The conceptual leap from 1D to 2D is significant. But once you see the pattern, it becomes mechanical.
Typical Problem Types
Let's categorize the most common 2D sliding window problems.
Sum of Submatrix of Size k x k (Fixed Size)
Problem Type: Find the maximum sum of any submatrix.
Example: Given a grid:
[[1, 2, 3],
[4, 5, 6],
[7, 8, 9]]Find the max sum of a submatrix.
Approach: Use a true 2D sliding window:
- Precompute prefix sums for range queries
- Slide the window across the matrix
Complexity: preprocessing, per query
Template:
def maxSumSubmatrix(matrix: List[List[int]], k: int) -> int:
rows, cols = len(matrix), len(matrix[0])
# Build 2D prefix sum
prefix = [[0] * (cols + 1) for _ in range(rows + 1)]
for r in range(1, rows + 1):
for c in range(1, cols + 1):
prefix[r][c] = (matrix[r-1][c-1] +
prefix[r-1][c] +
prefix[r][c-1] -
prefix[r-1][c-1])
max_sum = float('-inf')
# Slide the k x k window
for r in range(k, rows + 1):
for c in range(k, cols + 1):
# Sum of submatrix from (r-k, c-k) to (r-1, c-1)
total = (prefix[r][c] -
prefix[r-k][c] -
prefix[r][c-k] +
prefix[r-k][c-k])
max_sum = max(max_sum, total)
return max_sumVariable Size: Maximum Submatrix Sum / Kadane's 2D Extension
Problem Type: Find the maximum sum of any submatrix (no size constraint).
Example: LeetCode 363 - Max Sum of Rectangle No Larger Than K
Approach: Fix top and bottom rows, compress columns into a 1D array, apply Kadane's algorithm (or 1D sliding window variant).
Complexity: or with binary search
Other Variants
- Max rectangle of 1's: LeetCode 85 (Maximal Rectangle)
- Count subarrays with sum ≤ target: Use TreeMap for ordered sums
- Largest square of 1's: DP + sliding window hybrid
General Approach / Template
Here's the universal pattern for 2D sliding window with variable size.
Compress Rows → Turn into 1D Sliding Window
Core Idea:
- Fix the top row (
r1) and bottom row (r2) - Compress all rows between
r1andr2into a single 1D array by summing each column - Apply 1D sliding window (or Kadane's, or prefix sum) on this compressed array
Visual Example:
Matrix:
[1, 2, -1, 4]
[3, -2, 2, 1]
[2, 1, 3, -3]Fix rows 0 to 1 (top two rows). Compress columns:
Column sums: [1+3, 2+(-2), -1+2, 4+1] = [4, 0, 1, 5]Now solve the 1D problem: "Find max subarray sum in [4, 0, 1, 5]" → Answer: 10 (entire array)
Maintain Window Height + Width
For variable-size windows, you maintain:
- Height: The range
[r1, r2](fixed in each iteration) - Width: The 1D sliding window on compressed columns
Code Snippet (Pseudo-code)
Maximum Sum Submatrix (Variable Size)
def maxSumSubmatrix(matrix: List[List[int]]) -> int:
if not matrix:
return 0
rows, cols = len(matrix), len(matrix[0])
max_sum = float('-inf')
# Fix top row
for r1 in range(rows):
# Column sums for rows [r1, r2]
col_sums = [0] * cols
# Expand bottom row
for r2 in range(r1, rows):
# Add current row to column sums
for c in range(cols):
col_sums[c] += matrix[r2][c]
# Now solve 1D problem: max subarray sum in col_sums
# Using Kadane's algorithm
current_sum = 0
for val in col_sums:
current_sum = max(val, current_sum + val)
max_sum = max(max_sum, current_sum)
return max_sumComplexity Analysis:
- Outer loop (r1):
- Middle loop (r2):
- Inner loop (columns):
- Kadane's:
Total:
When to Use: Most 2D sliding window problems with variable size. Make sure you understand 1D sliding window intuition before attempting 2D problems.
Advanced: Maximum Sum Rectangle No Larger Than K
This is LeetCode 363—the final boss of 2D sliding window.
Problem: Find the max sum of a submatrix where sum ≤ k.
Challenge: Kadane's doesn't work because you need to stay under a threshold.
Solution: Use an ordered set (TreeSet in Java, SortedList in Python) to track prefix sums.
from sortedcontainers import SortedList
def maxSumSubmatrix(matrix: List[List[int]], k: int) -> int:
rows, cols = len(matrix), len(matrix[0])
max_sum = float('-inf')
for r1 in range(rows):
col_sums = [0] * cols
for r2 in range(r1, rows):
for c in range(cols):
col_sums[c] += matrix[r2][c]
# Find max subarray sum <= k in col_sums
max_sum = max(max_sum, maxSubarraySumLessThanK(col_sums, k))
return max_sum
def maxSubarraySumLessThanK(arr: List[int], k: int) -> int:
prefix_sums = SortedList([0])
current_sum = 0
max_sum = float('-inf')
for val in arr:
current_sum += val
# Find smallest prefix such that (current_sum - prefix) <= k
# Which means prefix >= current_sum - k
target = current_sum - k
idx = prefix_sums.bisect_left(target)
if idx < len(prefix_sums):
max_sum = max(max_sum, current_sum - prefix_sums[idx])
prefix_sums.add(current_sum)
return max_sumComplexity:
Why It Works: The TreeSet maintains sorted prefix sums, allowing binary search for the best split point.
Common Pitfalls & Tips
Forgetting to Reset State on Row Shift
The Mistake: When you move from r2 = 1 to r2 = 2, you forget to reset col_sums for the new r1.
Example:
# WRONG
col_sums = [0] * cols # Should be inside r1 loop!
for r1 in range(rows):
for r2 in range(r1, rows):
# col_sums carries stale data from previous r1The Fix: Initialize col_sums inside the r1 loop:
for r1 in range(rows):
col_sums = [0] * cols # CORRECT: Fresh for each r1
for r2 in range(r1, rows):
# ...Off-by-One Boundaries in 2D
The Mistake: Confusing inclusive vs exclusive boundaries.
When using prefix sums:
prefix[r][c]represents sum from(0, 0)to(r - 1, c - 1)(exclusive indexing)- To get sum of submatrix
(r1, c1)to(r2, c2)(inclusive):total = prefix[r2+1][c2+1] - prefix[r1][c2+1] - prefix[r2+1][c1] + prefix[r1][c1]python
Tip: Draw a small 3×3 matrix and manually trace indices to verify.
Using Kadane's When You Need Bounded Sums
The Mistake: Applying Kadane's algorithm when the problem asks for "sum ≤ k" or "sum closest to k."
Kadane's finds the maximum sum subarray, not the maximum under a constraint.
The Fix: Use the TreeSet/SortedList approach shown above.
Example: Debugging a Failed Case
Problem: Your code works on small matrices but fails on:
[[ 5, -4, -3, 4],
[-3, -4, 4, 5],
[ 5, 1, 5, -4]]Debug Steps:
- Print
col_sumsfor each(r1, r2)pair - Verify the 1D solution is correct for those compressed arrays
- Check if
col_sumsis being reset properly - Manually compute the expected answer for one submatrix
Common Issue: col_sums not reset, causing sums to accumulate across different r1 values.
Takeaways & Practice Plan
Key Principles
- Never enumerate all rectangles: That's . Always compress.
- Fix two boundaries, slide the other dimension: Usually fix rows, slide columns.
- Reset state carefully: Initialize fresh arrays for each outer loop iteration.
- Use prefix sums for fixed-size: sum queries after preprocessing.
- Use compression + 1D for variable-size: Reduces to a problem you already know.
Practice Plan
Week 1: Fixed-Size Windows
- Implement 2D prefix sums from scratch
- Solve: "Max sum of submatrix"
- Verify correctness on and matrices
Week 2: Variable-Size with Kadane's
- Learn Kadane's algorithm if you haven't
- Solve: "Maximum Sum Submatrix" (no constraints)
- Practice: LeetCode 85 (Maximal Rectangle)
Week 3: Advanced Constraints
- Implement TreeSet-based bounded sum solution
- Solve: LeetCode 363 (Max Sum Rectangle No Larger Than K)
- Understand why TreeSet is per operation
Daily Practice: 1 problem every 2 days. 2D problems require deeper understanding than 1D—don't rush.
Important: Only attempt 2D problems after mastering 1D. See our top sliding window problems list for a structured progression.
Related Patterns to Study
- 1D Kadane's Algorithm: Foundation for max subarray
- Prefix Sums: Essential for range queries
- Sliding Window Template: 1D foundation
- Monotonic Deque: For "max in every window" problems
FAQ
Q: Is 2D sliding window actually common in interviews?
A: Less common than 1D, but it appears in senior-level interviews at top companies. If you're targeting Google, Meta, or competitive programming, you should know it.
Q: Can I use the same template for all 2D problems?
A: The compression approach (fix rows, slide columns) works for 90% of problems. Fixed-size problems are easier with 2D prefix sums.
Q: What if the matrix is very large ()?
A: might be too slow. Look for problem-specific optimizations (e.g., sparse matrices, monotonic properties) or alternative approaches.
Q: Do I need to memorize the prefix sum formula?
A: Yes. The formula prefix[r2 + 1][c2 + 1] - prefix[r1][c2 + 1] - prefix[r2 + 1][c1] + prefix[r1][c1] is worth memorizing. Or use the principle of inclusion-exclusion to derive it.
Q: What's the difference between DP and 2D sliding window?
A: They can overlap. Some DP problems (like "Maximal Rectangle") use sliding window as a subroutine. DP is about optimal substructure; sliding window is about maintaining a range efficiently.
Q: Should I practice 2D problems if I'm a beginner?
A: No. Master 1D sliding window first. Solve at least 15-20 1D problems before attempting 2D. The jump is significant.
Q: How do I know if a matrix problem is sliding window vs DP?
A: If you're optimizing a contiguous rectangular region (e.g., "max sum submatrix"), think sliding window. If you're building solutions from smaller subproblems (e.g., "unique paths"), think DP.
Ready to Practice This Pattern?
Apply this pattern with LeetCopilot's AI-powered hints, notes, and mock interviews. Transform your coding interview preparation today.
