Backtrack
A 3-cycle like below consists of a 3-room path () and an edge from the last room to the first room (
).

So, we consider each room as the head of a possible 3-cycle, generate 3-length path and check if there is an edge from last room to first.
If largest number of corridors from a room is , time:
, space, that of adjacency list:
.
class Solution:
def get_adj_list(self, n, corridors) -> Dict[int, Set[int]]:
adj_list = { u: set() for u in range(1, n+1) }
for u, v in corridors:
adj_list[u].add(v)
adj_list[v].add(u)
return adj_list
def explore(self, adj_list, path, visited, cycles):
if len(path) == 3:
if path[0] in adj_list[path[-1]]:
cycles.add( tuple( sorted(path) ) )
return
for v in adj_list[ path[-1] ]:
if v in visited:
continue
visited.add(v)
self.explore(adj_list, path+[v], visited, cycles)
visited.remove(v)
def numberOfPaths(self, n: int, corridors: List[List[int]]) -> int:
adj_list = self.get_adj_list(n, corridors)
cycles = set()
for u in range(1, n+1):
self.explore(adj_list, [u], {u}, cycles)
return len(cycles)
Check all possible 3-rooms
Generate all groups of three rooms and check if they are in a cycle.
Time: , space is for adjacency list:
.
class Solution:
def get_adj_list(self, n, corridors) -> Dict[int, Set[int]]:
adj_list = { u: set() for u in range(1, n+1) }
for u, v in corridors:
adj_list[u].add(v)
adj_list[v].add(u)
return adj_list
def numberOfPaths(self, n: int, corridors: List[List[int]]) -> int:
adj_list = self.get_adj_list(n, corridors)
count = 0
for u in range(1, n+1):
if not adj_list[u]:
continue
for v in range(u+1, n+1):
if not adj_list[v] or v not in adj_list[u]:
continue
for w in range(v+1, n+1):
if not adj_list[w] or w not in adj_list[v]:
continue
if u in adj_list[w]:
count += 1
return count
Find third member per edge
For an edge , we need a
that is adjacent to both
and
, so we can take the intersection of the
‘s edge-set and
‘s edge-set.
If there are total corridors, time:
. Space, for adjacency list,
.
class Solution:
def get_adj_list(self, n, corridors) -> Dict[int, Set[int]]:
adj_list = { u: set() for u in range(1, n+1) }
for u, v in corridors:
adj_list[u].add(v)
adj_list[v].add(u)
return adj_list
def numberOfPaths(self, n: int, corridors: List[List[int]]) -> int:
adj_list = self.get_adj_list(n, corridors)
cycles = set()
for u, v in corridors:
ws = adj_list[u] & adj_list[v]
for w in ws:
cycles.add( tuple( sorted([u, v, w]) ) )
return len(cycles)
If we take the intersection as we are building the adjacency list, a cycle will be counted once when we consider the third edge, so we do not need to de-duplicate.

class Solution:
def numberOfPaths(self, n: int, corridors: List[List[int]]) -> int:
adj_list = {u: set() for u in range(1, n+1)}
count = 0
for u, v in corridors:
adj_list[u].add(v)
adj_list[v].add(u)
count += len(adj_list[u] & adj_list[v])
return count
Leave a comment