[
graph
graph algo
connected components
]
BinarySearch 0111 Short Circuit
Problem statement
https://binarysearch.com/problems/Short-Circuit/
Solution 1
The idea is that we need to construc Eulerian cycle: it is possible to construct it if and only if
- For each node indegree is equal to outdegree
- If graph has only one connected component.
Complexity
It is O(n)
for time and O(26)
for space.
Code
class Solution:
def solve(self, words):
def kosaraju(g, n):
vis, l, comps = [False]*n, [0]*n, [0]*n
global time
time, transp = n, [[]] * n
def visit(u):
global time
if vis[u]: return
vis[u] = True
for v in g[u]:
visit(v)
transp[v] = transp[v] + [u]
time -= 1
l[time] = u
def assign(u, root):
if not vis[u]: return
vis[u] = False
comps[u] = root
for v in transp[u]:
assign(v, root)
for u in range(n): visit(u)
for u in l: assign(u, u)
return comps
letters = set(w[0] for w in words) | set(w[-1] for w in words)
d = {l:i for i, l in enumerate(letters)}
G = defaultdict(set)
G_bal = Counter()
for w in words:
G[d[w[0]]].add(d[w[-1]])
G_bal[w[0]] += 1
G_bal[w[-1]] -= 1
if sum(abs(i) for i in G_bal.values()) != 0: return False
out = kosaraju(G, len(G))
return out == [0] * len(d)
Solution 2
In fact to check strong connectivity we can use Leetcode 332. Reconstruct Itinerary and Hierholzer’s algorithm, which also can return path as well and which will be shorter.
Complexity
Still O(n)
.
Code
# not mine code
class Solution:
def solve(self, words):
adj = [[] for i in range(128)]
out, visited, path = [0] * 128, [0] * 128, []
for w in words:
s, e = ord(w[0]) - ord("a"), ord(w[-1]) - ord("a")
adj[s].append(e)
out[s] += 1
out[e] -= 1
visited[s] = visited[e] = 1
def dfs(start):
while len(adj[start]) > 0:
node = adj[start].pop()
dfs(node)
path.append(start)
visited[start] = 0
dfs(ord(words[0][0]) - ord("a"))
return path[0] == path[-1] and sum(visited) == 0 and all(out) == 0