Determine blockage and parse HTML tokens
Company: Snapchat
Role: Software Engineer
Category: Coding & Algorithms
Difficulty: Medium
Interview Round: Onsite
Quick Answer: This question evaluates computational geometry and graph connectivity for the circular-stones subproblem and parsing plus tree data-structure manipulation for the HTML-like token subproblem, measuring skills in modeling spatial overlap, graph traversal/union operations, hierarchical DOM construction, and dynamic node insertion/deletion.
Constraints
- 0 <= n <= 2000, where n is the number of stones
- 1 <= width <= 10^9
- -10^9 <= xi, yi <= 10^9
- 0 <= ri <= 10^9
- Two stones connect if (xi - xj)^2 + (yi - yj)^2 <= (ri + rj)^2
- A chain blocks the river if it connects y <= 0 to y >= width via overlaps/touches
- Use integer arithmetic (squared distances) to avoid floating-point errors
Solution
from typing import List, Tuple
def can_block_river(width: int, stones: List[Tuple[int, int, int]]) -> bool:
n = len(stones)
if n == 0:
return False
# Disjoint Set Union (Union-Find)
parent = list(range(n + 2))
rank = [0] * (n + 2)
TOP = n # virtual node for top bank
BOTTOM = n+1 # virtual node for bottom bank
def find(a: int) -> int:
while parent[a] != a:
parent[a] = parent[parent[a]]
a = parent[a]
return a
def union(a: int, b: int) -> None:
ra, rb = find(a), find(b)
if ra == rb:
return
if rank[ra] < rank[rb]:
parent[ra] = rb
elif rank[ra] > rank[rb]:
parent[rb] = ra
else:
parent[rb] = ra
rank[ra] += 1
# Connect stones to banks if they touch
for i, (x, y, r) in enumerate(stones):
if y - r <= 0:
union(i, BOTTOM)
if y + r >= width:
union(i, TOP)
# Connect overlapping/touching stones
for i in range(n):
x1, y1, r1 = stones[i]
for j in range(i + 1, n):
x2, y2, r2 = stones[j]
dx = x1 - x2
dy = y1 - y2
rsum = r1 + r2
if dx*dx + dy*dy <= rsum*rsum:
union(i, j)
return find(TOP) == find(BOTTOM)