Skip to content

Commit 650bdec

Browse files
Restore neighbor helper to avoid defaultdict mutation
1 parent 1b8189b commit 650bdec

1 file changed

Lines changed: 23 additions & 12 deletions

File tree

graphs/check_bipatrite.py

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,24 @@
11
from collections import defaultdict, deque
2+
from collections.abc import Iterable, Mapping
23

34

4-
def is_bipartite_dfs(graph: defaultdict[int, list[int]]) -> bool:
5+
Graph = Mapping[int, Iterable[int]]
6+
_MISSING = object()
7+
8+
9+
def _iter_neighbors(graph: Graph, node: int) -> Iterable[int]:
10+
neighbors = graph.get(node, _MISSING)
11+
if neighbors is not _MISSING:
12+
return neighbors
13+
14+
default_factory = getattr(graph, "default_factory", None)
15+
if callable(default_factory):
16+
return default_factory()
17+
18+
raise KeyError(node)
19+
20+
21+
def is_bipartite_dfs(graph: Graph) -> bool:
522
"""
623
Check if a graph is bipartite using depth-first search (DFS).
724
@@ -15,11 +32,8 @@ def is_bipartite_dfs(graph: defaultdict[int, list[int]]) -> bool:
1532
vertices within the same set are connected by an edge.
1633
1734
Examples:
18-
# FIXME: This test should pass.
1935
>>> is_bipartite_dfs(defaultdict(list, {0: [1, 2], 1: [0, 3], 2: [0, 4]}))
20-
Traceback (most recent call last):
21-
...
22-
RuntimeError: dictionary changed size during iteration
36+
True
2337
>>> is_bipartite_dfs(defaultdict(list, {0: [1, 2], 1: [0, 3], 2: [0, 1]}))
2438
False
2539
>>> is_bipartite_dfs({})
@@ -78,7 +92,7 @@ def depth_first_search(node: int, color: int) -> bool:
7892
"""
7993
if visited[node] == -1:
8094
visited[node] = color
81-
for neighbor in graph[node]:
95+
for neighbor in _iter_neighbors(graph, node):
8296
if not depth_first_search(neighbor, 1 - color):
8397
return False
8498
return visited[node] == color
@@ -90,7 +104,7 @@ def depth_first_search(node: int, color: int) -> bool:
90104
return True
91105

92106

93-
def is_bipartite_bfs(graph: defaultdict[int, list[int]]) -> bool:
107+
def is_bipartite_bfs(graph: Graph) -> bool:
94108
"""
95109
Check if a graph is bipartite using a breadth-first search (BFS).
96110
@@ -104,11 +118,8 @@ def is_bipartite_bfs(graph: defaultdict[int, list[int]]) -> bool:
104118
vertices within the same set are connected by an edge.
105119
106120
Examples:
107-
# FIXME: This test should pass.
108121
>>> is_bipartite_bfs(defaultdict(list, {0: [1, 2], 1: [0, 3], 2: [0, 4]}))
109-
Traceback (most recent call last):
110-
...
111-
RuntimeError: dictionary changed size during iteration
122+
True
112123
>>> is_bipartite_bfs(defaultdict(list, {0: [1, 2], 1: [0, 2], 2: [0, 1]}))
113124
False
114125
>>> is_bipartite_bfs({})
@@ -160,7 +171,7 @@ def is_bipartite_bfs(graph: defaultdict[int, list[int]]) -> bool:
160171
visited[node] = 0
161172
while queue:
162173
curr_node = queue.popleft()
163-
for neighbor in graph[curr_node]:
174+
for neighbor in _iter_neighbors(graph, curr_node):
164175
if visited[neighbor] == -1:
165176
visited[neighbor] = 1 - visited[curr_node]
166177
queue.append(neighbor)

0 commit comments

Comments
 (0)