Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# 3070. Count Submatrices with Top-Left Element and Sum Less Than k

[LeetCode Link](https://leetcode.com/problems/count-submatrices-with-top-left-element-and-sum-less-than-k/)

Difficulty: Medium
Topics: Array, Matrix, Prefix Sum
Acceptance Rate: 62.8%

## Hints

### Hint 1

Every submatrix that contains the top-left element of the grid is uniquely determined by one thing — its bottom-right corner. Think about what that means for how many submatrices you actually need to consider.

### Hint 2

If you can quickly compute the sum of any submatrix from (0, 0) to (i, j), you can check each candidate in O(1) time. A classic technique lets you build such a lookup over the entire grid in a single pass. Look into 2D prefix sums.

### Hint 3

Because all grid values are non-negative, the prefix sums are monotonically non-decreasing along each row (left to right) and each column (top to bottom). This means once a submatrix sum exceeds k for some column j in row i, every wider submatrix in that row will also exceed k — so you can break out of the inner loop early.

## Approach

Since every valid submatrix must include the top-left corner (0, 0), each submatrix is fully defined by its bottom-right corner (i, j). The sum of the submatrix from (0, 0) to (i, j) can be computed using the 2D prefix sum formula:

```
prefix[i][j] = grid[i][j]
+ prefix[i-1][j] (sum of everything above)
+ prefix[i][j-1] (sum of everything to the left)
- prefix[i-1][j-1] (subtract double-counted region)
```

We compute the prefix sums in-place (or in a separate array) row by row, left to right. For each cell (i, j), if `prefix[i][j] <= k`, we increment our count. Because all values are non-negative, prefix sums only grow as j increases within a row, so we can break early when the sum exceeds k.

**Walkthrough with Example 1** (`grid = [[7,6,3],[6,6,1]], k = 18`):

| (i,j) | prefix | <= 18? |
|--------|--------|--------|
| (0,0) | 7 | yes |
| (0,1) | 13 | yes |
| (0,2) | 16 | yes |
| (1,0) | 13 | yes |
| (1,1) | 25 | no — break row |

Count = 4, which matches the expected output.

## Complexity Analysis

Time Complexity: O(m × n) — we visit each cell once to compute the prefix sum and check the condition.

Space Complexity: O(1) if we modify the grid in-place, or O(m × n) if we use a separate prefix sum array. The solution below modifies the grid in-place.

## Edge Cases

- **Single cell grid**: The answer is 1 if `grid[0][0] <= k`, otherwise 0.
- **First cell exceeds k**: If `grid[0][0] > k`, no submatrix can satisfy the condition, return 0 immediately.
- **All zeros**: Every submatrix has sum 0 which is always <= k, so the answer is m × n.
- **Large k**: If k is large enough that the total sum of the grid fits, the answer is m × n.
- **Single row or single column**: Degenerates to a 1D prefix sum problem; the early-break optimization still applies.
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
---
number: "3070"
frontend_id: "3070"
title: "Count Submatrices with Top-Left Element and Sum Less Than k"
slug: "count-submatrices-with-top-left-element-and-sum-less-than-k"
difficulty: "Medium"
topics:
- "Array"
- "Matrix"
- "Prefix Sum"
acceptance_rate: 6279.6
is_premium: false
created_at: "2026-03-18T03:24:30.630792+00:00"
fetched_at: "2026-03-18T03:24:30.630792+00:00"
link: "https://leetcode.com/problems/count-submatrices-with-top-left-element-and-sum-less-than-k/"
date: "2026-03-18"
---

# 3070. Count Submatrices with Top-Left Element and Sum Less Than k

You are given a **0-indexed** integer matrix `grid` and an integer `k`.

Return _the**number** of submatrices that contain the top-left element of the_ `grid`, _and have a sum less than or equal to_`k`.



**Example 1:**

![](https://assets.leetcode.com/uploads/2024/01/01/example1.png)


**Input:** grid = [[7,6,3],[6,6,1]], k = 18
**Output:** 4
**Explanation:** There are only 4 submatrices, shown in the image above, that contain the top-left element of grid, and have a sum less than or equal to 18.

**Example 2:**

![](https://assets.leetcode.com/uploads/2024/01/01/example21.png)


**Input:** grid = [[7,2,9],[1,5,0],[2,6,6]], k = 20
**Output:** 6
**Explanation:** There are only 6 submatrices, shown in the image above, that contain the top-left element of grid, and have a sum less than or equal to 20.




**Constraints:**

* `m == grid.length `
* `n == grid[i].length`
* `1 <= n, m <= 1000 `
* `0 <= grid[i][j] <= 1000`
* `1 <= k <= 109`
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package main

// countSubmatrices counts submatrices containing the top-left element (0,0)
// whose sum is <= k. We compute 2D prefix sums in-place and count valid cells.
// Since all values are non-negative, we break early when a row's running sum exceeds k.
func countSubmatrices(grid [][]int, k int) int {
m := len(grid)
n := len(grid[0])
count := 0

for i := 0; i < m; i++ {
for j := 0; j < n; j++ {
if i > 0 {
grid[i][j] += grid[i-1][j]
}
if j > 0 {
grid[i][j] += grid[i][j-1]
}
if i > 0 && j > 0 {
grid[i][j] -= grid[i-1][j-1]
}
if grid[i][j] <= k {
count++
} else {
break // values are non-negative, so wider submatrices only grow
}
}
}

return count
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package main

import "testing"

func TestCountSubmatrices(t *testing.T) {
tests := []struct {
name string
grid [][]int
k int
expected int
}{
{
name: "example 1: 2x3 grid k=18",
grid: [][]int{{7, 6, 3}, {6, 6, 1}},
k: 18,
expected: 4,
},
{
name: "example 2: 3x3 grid k=20",
grid: [][]int{{7, 2, 9}, {1, 5, 0}, {2, 6, 6}},
k: 20,
expected: 6,
},
{
name: "edge case: single cell within k",
grid: [][]int{{5}},
k: 5,
expected: 1,
},
{
name: "edge case: single cell exceeds k",
grid: [][]int{{10}},
k: 3,
expected: 0,
},
{
name: "edge case: all zeros",
grid: [][]int{{0, 0}, {0, 0}},
k: 0,
expected: 4,
},
{
name: "edge case: single row",
grid: [][]int{{1, 2, 3, 4}},
k: 6,
expected: 3,
},
{
name: "edge case: single column",
grid: [][]int{{1}, {2}, {3}, {4}},
k: 6,
expected: 3,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
// Deep copy grid since the solution modifies it in-place
grid := make([][]int, len(tt.grid))
for i := range tt.grid {
grid[i] = make([]int, len(tt.grid[i]))
copy(grid[i], tt.grid[i])
}
result := countSubmatrices(grid, tt.k)
if result != tt.expected {
t.Errorf("got %d, want %d", result, tt.expected)
}
})
}
}