HardArrayTwo PointersBreadth-First SearchUnion FindSortingHeapUpdated Sep 2026

2503. Maximum Number of Points from Grid Queries

Asked at Uber

Difficulty

Hard

Time

O(m*n*log(m*n) + k*log(k))

Space

O(m*n + k)

Pattern

Array

Companies

1

Problem

You are given an m x n grid of positive integers and an array queries. For each query value q, you start at the top-left cell (0, 0) and try to collect points.

You may step from a cell to any of its 4 neighbors (up, down, left, right). You may also revisit cells as many times as you like. The rule is: you can only enter a cell if q is strictly greater than the value stored in that cell. The first time you visit a cell you earn 1 point; revisiting it earns nothing. The moment you stand on a cell whose value is >= q, the process stops.

For each query, return the maximum number of points you can collect. The answer array must match the original order of queries.

Reach cells smaller than the query

grid012012123257351q=5: five green cells have value < 5, so the score is5
For q=5 you start at 1 and can only step onto cells whose value is below 5, collecting one point per new cell.

Constraints

  • ●m == grid.length
  • ●n == grid[i].length
  • ●2 <= m, n <= 1000
  • ●4 <= m * n <= 10^5
  • ●k == queries.length
  • ●1 <= k <= 10^4
  • ●1 <= grid[i][j], queries[i] <= 10^6

Examples

Example 1
Inputgrid = [[1,2,3],[2,5,7],[3,5,1]], queries = [5,6,2]
Output[5,8,1]
WhyFor q=5 you can reach the cells with values 1,2,3,2,3 — that is 5 cells. For q=6 the cell with value 5 also opens up, plus more neighbors, giving 8. For q=2 only the starting cell (value 1) is smaller than 2, so you get 1 point.
Example 2
Inputgrid = [[5,2,1],[1,1,2]], queries = [3]
Output[0]
WhyThe starting cell has value 5, which is not strictly less than 3, so the process ends immediately and you score 0.

Asked At

1 companies
CompanyDifficulty
UberHardView all Uber questions →

How to Think About It

1

Brute force: for each query, run a BFS/DFS from (0,0) counting cells with value < query. Time: O(q * m * n) where q is number of queries. Too slow for large grids.

2

Key insight: sort queries in ascending order and process them incrementally. As the query threshold increases, more cells become accessible. Use a min-heap to always expand the cheapest cell first.

3

The BFS + heap approach: start with (0,0) in a min-heap. Pop the smallest value cell. If its value < current query, add it to the count and push its unvisited neighbors. Repeat until the heap top is >= query.

4

Union-Find alternative: sort all cells by value and queries by value. Use union-find to connect cells as they become "active." For each query, activate all cells with value < query and union with active neighbors. Count the size of the component containing (0,0).

5

Why sort queries: processing queries in ascending order lets you reuse work. Cells activated for query k are still active for query k+1. You never deactivate cells, only add more.

Optimal Approach

Step 1: Create a sorted copy of queries with their original indices.
Step 2: Initialize a min-heap with (grid[0][0], 0, 0) and a visited set.
Step 3: Process queries in ascending order. For each query:

  • While the heap is not empty and the top value < query:
    • Pop the cell, increment count
    • Push unvisited neighbors (up, down, left, right) with value < query
  • Store the count for this query
    Step 4: Return results in the original query order.

Walkthrough for grid [[1,3],[2,4]], queries [2,3,5]:

  • Sorted queries: [(2,0), (3,1), (5,2)]
  • Heap: [(1,0,0)], visited: {(0,0)}
  • Query 2: pop 1<2, count=1. Push (3,0,1) and (2,1,0). Heap: [(2,1,0),(3,0,1)]. Top=2>=2. Result[0]=1.
  • Query 3: pop 2<3, count=2. Push (4,1,1). Heap: [(3,0,1),(4,1,1)]. Top=3>=3. Result[1]=2.
  • Query 5: pop 3<5, count=3. Pop 4<5, count=4. Heap empty. Result[2]=4.

Time: O(m*n*log(m*n) + q*log(q)) for heap operations and sorting. Space: O(m*n + q) for the heap, visited set, and result array.

Sort queries, grow one heap

grid01011324Start: push (0,0) with value 1 into the min-heapgrid01011324q=3: pop value 2, count becomes 2, push its neighborvalue 4while heap top < q: pop cell, count += 1 push unvisited neighborsanswer[orig] = count
Queries are handled from small to large, so the heap only ever grows — cells unlocked for one query stay unlocked for the next.
ComplexityTime O(m*n*log(m*n) + k*log(k))Space O(m*n + k)Each cell enters and leaves the min-heap once, and the queries are sorted once; the heap and visited set hold up to m*n entries.

What Trips People Up in Real Interviews

1

Processing queries in the given order instead of sorting. Without sorting, you can't reuse work between queries. Always sort queries and map results back to original order using indices.

2

Using BFS with a queue instead of a min-heap. A regular queue doesn't guarantee you expand cells in order of increasing value. A min-heap does, which is essential for the incremental activation to work correctly.

3

Forgetting to mark cells as visited. Without a visited set, you might process the same cell multiple times, leading to incorrect counts and infinite loops in the BFS.

4

Not handling the edge case where (0,0) itself has a value >= query. In that case, the count is 0 because you can't even start. The BFS/heap should handle this naturally if implemented correctly.

5

Confusing "strictly less than" with "less than or equal to." The problem says values strictly less than the query. grid[i][j] < query, not <=. This is a subtle but critical distinction.

Solution Code

O(m*n*log(m*n) + k*log(k)) time
import heapq

def maxPoints(grid, queries):
    m, n = len(grid), len(grid[0])
    sorted_queries = sorted([(q, i) for i, q in enumerate(queries)])
    result = [0] * len(queries)

    heap = [(grid[0][0], 0, 0)]
    visited = {(0, 0)}
    count = 0

    for q, orig_idx in sorted_queries:
        while heap and heap[0][0] < q:
            val, r, c = heapq.heappop(heap)
            count += 1
            for dr, dc in [(-1,0),(1,0),(0,-1),(0,1)]:
                nr, nc = r + dr, c + dc
                if 0 <= nr < m and 0 <= nc < n and (nr, nc) not in visited:
                    visited.add((nr, nc))
                    heapq.heappush(heap, (grid[nr][nc], nr, nc))
        result[orig_idx] = count

    return result

Pro at DSA?

Test your skills with a real FAANG-style mock interview.

Start a Mock Interview →

Frequently Asked Questions

What is the Maximum Number of Points from Grid Queries problem?

Given an m x n grid of positive integers and an array of queries, for each query find how many cells have values strictly less than the query value, starting from the top-left corner and moving to adjacent cells. Return the results for all queries.

How do you solve Maximum Number of Points from Grid Queries?

The optimal approach runs in O(m*n*log(m*n) + k*log(k)) time and O(m*n + k) space. Scroll up to "Optimal Approach" for the step-by-step walkthrough, diagrams, and code in Python, C++ and Java.

What companies ask Maximum Number of Points from Grid Queries?

Maximum Number of Points from Grid Queries is asked at Uber. It is a hard difficulty problem.

What are common mistakes on Maximum Number of Points from Grid Queries?
  • Processing queries in the given order instead of sorting. Without sorting, you can't reuse work between queries. Always sort queries and map results back to original order using indices.
  • Using BFS with a queue instead of a `min-heap`. A regular queue doesn't guarantee you expand cells in order of increasing value. A `min-heap` does, which is essential for the incremental activation to work correctly.
  • Forgetting to mark cells as visited. Without a visited set, you might process the same cell multiple times, leading to incorrect counts and infinite loops in the BFS.
  • Not handling the edge case where (0,0) itself has a value >= query. In that case, the count is 0 because you can't even start. The BFS/heap should handle this naturally if implemented correctly.
  • Confusing "strictly less than" with "less than or equal to." The problem says values strictly less than the query. `grid[i][j] < query`, not `<=`. This is a subtle but critical distinction.