mirror of
https://github.com/prdlk/leetcode.git
synced 2026-11-02 21:22:43 +00:00
docs(docs): add and expand algorithm documentation
This commit is contained in:
1 parent
34bb305a96
commit
32a41bdcb0
10 files changed
+1061
-50
No files matched your search
@@ -0,0 +1,121 @@
|
||||
---
|
||||
title: Breadth-First Search
|
||||
---
|
||||
|
||||
# Breadth-First Search (BFS)
|
||||
|
||||
## The idea
|
||||
|
||||
You want a mango seller. You ask your friends first.
|
||||
No luck? You ask friends-of-friends. Then their friends.
|
||||
You search in **rings**, closest first.
|
||||
|
||||
That is BFS. It answers two questions:
|
||||
1. **Is there a path** from A to B?
|
||||
2. **What is the shortest path?** (unweighted — fewest hops)
|
||||
|
||||
BFS is *always* shortest path on unweighted graphs. First time you reach a node = fewest possible steps.
|
||||
|
||||
## The picture
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
YOU((You)) --> A((Alice))
|
||||
YOU --> B((Bob))
|
||||
A --> C((Claire))
|
||||
A --> D((Dan))
|
||||
B --> E((Eve))
|
||||
E --> M((Mango seller ✓))
|
||||
|
||||
style YOU fill:#1565c0,color:#fff
|
||||
style A fill:#6a1b9a,color:#fff
|
||||
style B fill:#6a1b9a,color:#fff
|
||||
style C fill:#ef6c00,color:#fff
|
||||
style D fill:#ef6c00,color:#fff
|
||||
style E fill:#ef6c00,color:#fff
|
||||
style M fill:#2e7d32,color:#fff
|
||||
```
|
||||
|
||||
Blue = start. Purple = ring 1. Orange = ring 2. Green = found at ring 3.
|
||||
|
||||
## The two tools
|
||||
|
||||
1. **Queue** — first in, first out. This keeps the rings in order.
|
||||
2. **Visited set** — never check the same node twice. Without it, cycles loop forever.
|
||||
|
||||
## The template
|
||||
|
||||
```python
|
||||
from collections import deque
|
||||
|
||||
def bfs(start, graph: dict) -> None:
|
||||
queue = deque([start])
|
||||
visited = {start}
|
||||
|
||||
while queue:
|
||||
level_size = len(queue) # snapshot = one full ring
|
||||
for _ in range(level_size):
|
||||
node = queue.popleft()
|
||||
# process node here
|
||||
for nxt in graph.get(node, []):
|
||||
if nxt not in visited:
|
||||
visited.add(nxt) # mark WHEN queued, not when popped
|
||||
queue.append(nxt)
|
||||
```
|
||||
|
||||
## Multi-source BFS (LC 994 — Rotting Oranges)
|
||||
|
||||
Start with *all* rotten oranges in the queue at once.
|
||||
Each ring = one minute of rot spreading.
|
||||
|
||||
```python
|
||||
from collections import deque
|
||||
|
||||
def oranges_rotting(grid: list[list[int]]) -> int:
|
||||
rows, cols = len(grid), len(grid[0])
|
||||
queue = deque()
|
||||
fresh = 0
|
||||
|
||||
for r in range(rows):
|
||||
for c in range(cols):
|
||||
if grid[r][c] == 2:
|
||||
queue.append((r, c))
|
||||
elif grid[r][c] == 1:
|
||||
fresh += 1
|
||||
|
||||
minutes = 0
|
||||
dirs = [(1, 0), (-1, 0), (0, 1), (0, -1)]
|
||||
|
||||
while queue and fresh > 0:
|
||||
for _ in range(len(queue)):
|
||||
r, c = queue.popleft()
|
||||
for dr, dc in dirs:
|
||||
nr, nc = r + dr, c + dc
|
||||
if 0 <= nr < rows and 0 <= nc < cols and grid[nr][nc] == 1:
|
||||
grid[nr][nc] = 2
|
||||
fresh -= 1
|
||||
queue.append((nr, nc))
|
||||
minutes += 1
|
||||
|
||||
return minutes if fresh == 0 else -1
|
||||
```
|
||||
|
||||
## Complexity
|
||||
|
||||
| | Time | Space |
|
||||
|---|---|---|
|
||||
| BFS | O(V + E) | O(V) |
|
||||
|
||||
V = nodes, E = edges. On a grid: O(rows × cols).
|
||||
|
||||
## Close-out ritual
|
||||
|
||||
Before you submit, say out loud:
|
||||
1. Time and space complexity.
|
||||
2. One edge case trace: empty graph, start = target, or unreachable target.
|
||||
|
||||
## Plan problems
|
||||
|
||||
**Tree BFS A-set:** LC 102 · 199 · 1448
|
||||
**Graph BFS A-set:** LC 994 · 127
|
||||
**B-set:** LC 103 · 637 · 909 · 433 · 286
|
||||
Reference in new issue
Block a user