You are given an m x n
integer matrix grid
and an array queries
of size k
. Find an array answer
of size k
such that for each integer queries[i]
you start in the top left cell of the matrix and repeat the following process:
queries[i]
is strictly greater than the value of the current cell that you are in, then you get one point if it is your first time visiting this cell, and you can move to any adjacent cell in all 4
directions: up, down, left, and right.After the process, answer[i]
is the maximum number of points you can get. Note that for each query you are allowed to visit the same cell multiple times.
Return the resulting array answer
.
Example 1:
Input: grid = [[1,2,3],[2,5,7],[3,5,1]], queries = [5,6,2]
Output: [5,8,1]
Explanation: The diagrams above show which cells we visit to get points for each query.
Example 2:
Input: grid = [[5,2,1],[1,1,2]], queries = [3]
Output: [0]
Explanation: We can not get any points because the value of the top left cell is already greater than or equal to 3.
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
class Solution:
def maxPoints(self, grid: list[list[int]], queries: list[int]) -> list[int]:
m, n = len(grid), len(grid[0])
directions = [(0, 1), (0, -1), (1, 0), (-1, 0)]
def bfs(threshold: int) -> int:
visited = [[False] * n for _ in range(m)]
q = [(0, 0)]
visited[0][0] = True
points = 0
if grid[0][0] >= threshold:
return 0
points = 1
while q:
row, col = q.pop(0)
for dr, dc in directions:
new_row, new_col = row + dr, col + dc
if 0 <= new_row < m and 0 <= new_col < n and not visited[new_row][new_col] and grid[new_row][new_col] < threshold:
visited[new_row][new_col] = True
q.append((new_row, new_col))
points += 1
return points
answer = []
for query in queries:
answer.append(bfs(query))
return answer
The provided code implements a brute-force approach using Breadth-First Search (BFS) to determine the maximum number of points obtainable for each query. It directly simulates the problem statement by exploring the grid for each query.
To optimize, we can use an offline query processing approach combined with the Union-Find data structure.
class UnionFind:
def __init__(self, n):
self.parent = list(range(n))
self.size = [1] * n
def find(self, x):
if self.parent[x] != x:
self.parent[x] = self.find(self.parent[x])
return self.parent[x]
def union(self, x, y):
rootX = self.find(x)
rootY = self.find(y)
if rootX != rootY:
if self.size[rootX] < self.size[rootY]:
rootX, rootY = rootY, rootX
self.parent[rootY] = rootX
self.size[rootX] += self.size[rootY]
class Solution:
def maxPoints(self, grid: list[list[int]], queries: list[int]) -> list[int]:
m, n = len(grid), len(grid[0])
cells = []
for i in range(m):
for j in range(n):
cells.append((grid[i][j], i, j))
cells.sort()
queries_with_indices = sorted([(queries[i], i) for i in range(len(queries))])
answers = [0] * len(queries)
uf = UnionFind(m * n)
directions = [(0, 1), (0, -1), (1, 0), (-1, 0)]
k = 0
visited = [[False] * n for _ in range(m)]
reachable = 0
for query, index in queries_with_indices:
while k < len(cells) and cells[k][0] < query:
_, row, col = cells[k]
idx = row * n + col
visited[row][col] = True
if row == 0 and col == 0:
reachable = uf.size[uf.find(idx)]
for dr, dc in directions:
new_row, new_col = row + dr, col + dc
if 0 <= new_row < m and 0 <= new_col < n and visited[new_row][new_col]:
new_idx = new_row * n + new_col
uf.union(idx, new_idx)
if visited[0][0]:
reachable = uf.size[uf.find(0)]
k += 1
answers[index] = reachable
return answers