Rilasciato · in miglioramento
Guida a Visita dei grafi · 5/6
Per ora questo capitolo è disponibile solo in inglese.
Most graph problems are half solved the moment you decide what the vertices and edges are. The four problems below were written for this guide and mirror patterns that come up often in coding interviews. Try each one before reading the solution.
A warehouse map is given as a list of strings. S is the robot's start, E the target, # a shelf (blocked) and . an empty cell. The robot moves one cell up, down, left or right per step. Return the minimum number of steps to reach the target, or -1 if it cannot.
Approach: cells are vertices and adjacent open cells share an edge. Every move costs 1, so the distance at which BFS first reaches E is the answer.
from collections import deque
def min_steps(grid):
rows, cols = len(grid), len(grid[0])
start = next((r, c) for r in range(rows) for c in range(cols) if grid[r][c] == "S")
dist = {start: 0}
queue = deque([start])
while queue:
r, c = queue.popleft()
if grid[r][c] == "E":
return dist[(r, c)]
for dr, dc in ((1, 0), (-1, 0), (0, 1), (0, -1)):
nr, nc = r + dr, c + dc
if 0 <= nr < rows and 0 <= nc < cols and grid[nr][nc] != "#" and (nr, nc) not in dist:
dist[(nr, nc)] = dist[(r, c)] + 1
queue.append((nr, nc))
return -1
print(min_steps(["S.#.", "..#E", "...."])) # 6The shelves force a detour through the bottom row, so the answer is 6 rather than the Manhattan distance of 4.
You have n servers and a list of cables (a, b). Servers linked directly or indirectly form one cluster. Return the number of clusters and the size of the largest one.
Approach: this is connected components. Start a traversal from every unvisited server and count how many servers it reaches. An explicit stack avoids the recursion limit.
def server_groups(n, cables):
adj = [[] for _ in range(n)]
for a, b in cables:
adj[a].append(b)
adj[b].append(a)
seen = [False] * n
groups, largest = 0, 0
for s in range(n):
if seen[s]:
continue
groups += 1
seen[s] = True
stack, size = [s], 0
while stack:
u = stack.pop()
size += 1
for v in adj[u]:
if not seen[v]:
seen[v] = True
stack.append(v)
largest = max(largest, size)
return groups, largest
print(server_groups(7, [(0, 1), (1, 2), (3, 4)])) # (4, 3)A dictionary maps each module to the modules that must be built before it. Return an order that builds everything; when several modules are ready at once, pick the alphabetically smallest. Return if there is a circular dependency.
NoneApproach: "A before B" is an edge A→B, so this is a topological sort. Replacing Kahn's queue with a heap always yields the smallest ready name.
import heapq
def build_order(deps):
indeg = {m: 0 for m in deps}
users = {m: [] for m in deps}
for module, needs in deps.items():
for need in needs:
users[need].append(module)
indeg[module] += 1
ready = [m for m, d in indeg.items() if d == 0]
heapq.heapify(ready)
order = []
while ready:
m = heapq.heappop(ready)
order.append(m)
for user in users[m]:
indeg[user] -= 1
if indeg[user] == 0:
heapq.heappush(ready, user)
return order if len(order) == len(deps) else None
deps = {"app": ["ui", "net"], "ui": ["core"], "net": ["core"], "core": [], "log": []}
print(build_order(deps)) # ['core', 'log', 'net', 'ui', 'app']
print(build_order({"a": ["b"], "b": ["a"]})) # NoneThe heap makes it O((V + E) log V). If any valid order will do, a plain deque is enough.
A grid contains several relays R. Every minute the signal spreads from each covered cell to adjacent empty cells .; # is a wall. Return how many minutes it takes to cover every empty cell, or -1 if some cell is never reached.
Approach: this is multi-source BFS. Enqueue every R at distance 0 before starting, and each cell's distance becomes its distance to the nearest relay. Running a separate BFS per relay would be far slower.
from collections import deque
def spread_time(grid):
rows, cols = len(grid), len(grid[0])
dist = [[-1] * cols for _ in range(rows)]
queue = deque()
for r in range(rows):
for c in range(cols):
if grid[r][c] == "R":
dist[r][c] = 0
queue.append((r, c))
while queue:
r, c = queue.popleft()
for dr, dc in ((1, 0), (-1, 0), (0, 1), (0, -1)):
nr, nc = r + dr, c + dc
if 0 <= nr < rows and 0 <= nc < cols and grid[nr][nc] == "." and dist[nr][nc] == -1:
dist[nr][nc] = dist[r][c] + 1
queue.append((nr, nc))
cells = [dist[r][c] for r in range(rows) for c in range(cols) if grid[r][c] == "."]
return -1 if -1 in cells else max(cells, default=0)
print(spread_time(["R..#", "...#", "#..R"])) # 2Grid shortest paths map to BFS, counting groups to connected components, ordering to topological sort, and many starting points to multi-source BFS. Before coding, write down what the vertices and edges are, whether edges are weighted, and whether they are directed; that habit solves more problems than any trick.
0 commenti
Accedi · Accedi per lasciare un commento.
Scrivi tu il primo commento.