about summary refs log tree commit diff
path: root/scratch
diff options
context:
space:
mode:
authorWilliam Carroll <wpcarro@gmail.com>2020-11-23T23·21+0000
committerWilliam Carroll <wpcarro@gmail.com>2020-11-23T23·21+0000
commit9549dbb2666e1032ad1f55218e68fd7ac636485e (patch)
tree70c089928040ed103dc567de3f2a99c5804ac5ea /scratch
parentc00eed469ccd5f4b53d98ceeeba32963dd593ed8 (diff)
Update BFS impls
I've subtly been implementing breadth-first traversals in graphs
incorrectly. The change is subtle, but updating `seen` needs to happen
immediately after queuing an item.

The results will remain the same, but the runtimes will differ dramatically. I
didn't notice this until I attempted to complete LeetCode's "count islands"
challenge, and LeetCode rejected my solution because it could not finish before
timing out. After looking at other candidates' solutions and comparing them to
mine, I couldn't see any difference... except for this subtle difference.

This SO answer provides a helpful explanation:
https://stackoverflow.com/questions/45623722/marking-node-as-visited-on-bfs-when-dequeuing

The take-away lesson here is to always call `seen.add(..)` immediately after
enqueuing.
Diffstat (limited to 'scratch')
-rw-r--r--scratch/facebook/count-islands.py2
-rw-r--r--scratch/facebook/graph-coloring.py4
2 files changed, 3 insertions, 3 deletions
diff --git a/scratch/facebook/count-islands.py b/scratch/facebook/count-islands.py
index a007684bca23..b876319b2f7a 100644
--- a/scratch/facebook/count-islands.py
+++ b/scratch/facebook/count-islands.py
@@ -8,6 +8,7 @@ def maybe_queue(row, col, game, q, seen):
     if row >= 0 and row < len(game) and col >= 0 and col < len(game[0]):
         if game[row][col] == 'L' and (row, col) not in seen:
             q.append((row, col))
+            seen.add((row, col))
 
 def visit_island(row, col, game, seen):
     """
@@ -18,7 +19,6 @@ def visit_island(row, col, game, seen):
     q.append((row, col))
     while q:
         row, col = q.popleft()
-        seen.add((row, col))
         maybe_queue(row - 1, col, game, q, seen) # UP
         maybe_queue(row + 1, col, game, q, seen) # DOWN
         maybe_queue(row, col - 1, game, q, seen) # LEFT
diff --git a/scratch/facebook/graph-coloring.py b/scratch/facebook/graph-coloring.py
index 17588166c871..e5b6d9c89332 100644
--- a/scratch/facebook/graph-coloring.py
+++ b/scratch/facebook/graph-coloring.py
@@ -25,10 +25,10 @@ class GraphNode(object):
         while xs:
             node = xs.popleft()
             result.append('{} ({})'.format(node.label, str(node.color)))
-            seen.add(node.label)
             for c in node.neighbors:
                 if c.label not in seen:
                     xs.append(c)
+                    seen.add(node.label)
         return ', '.join(result)
 
 def color_graph(graph, d):
@@ -40,11 +40,11 @@ def color_graph(graph, d):
     while xs:
         x, color = xs.popleft()
         x.color = color
-        seen.add(x.label)
         for c in x.neighbors:
             if c.label not in seen:
                 palette.advance()
                 xs.append((c, palette.get()))
+                seen.add(x.label)
 
 a = GraphNode('a')
 b = GraphNode('b')