TARGET DECK: Leetcode FILE TAGS: Medium


Intuition

  • This problem can be solved with DFS as applied in a standard fashion to graphs, but with a small change:
    • When creating your adjacency list, if you have for example [0: 1, 2, 3], then nodes 1, 2, and 3 will all be adjacent to 0 as well, but you don’t want to include them since you are checking for cycles that do not include those directly adjacent to node 0.
    • Additionally, check in the end whether the number of nodes visited equal the total number of nodes, since otherwise the graph might be disconnected.
  • I had first thought that if the node was disconnected

Complexity

Runtime

since we touch each pair of vertices and edges exactly once.

Space

due to axillary space needed for the adjacency list, which stores that many vertices and edges respectively.

Code

from collections import defaultdict
 
class Solution:
    def validTree(self, n: int, edges: List[List[int]]) -> bool:
        adj = defaultdict(list)
        for u, v in edges:
            adj[u].append(v)
            adj[v].append(u)
 
        visited = set()
        dp = {}
        def dfs(node, parent):
            if node in visited:
                return False
            if (node, parent) in dp:
                return dp[(node, parent)]
 
            visited.add(node)
            for v in adj[node]:
                if v != parent:
                    if dfs(v, node) == False:
                        dp[(node, parent)] = False
                        return False
            
            dp[(node, parent)] = True
            return True
 
        return dfs(0, None) and len(visited) == n

Notes

Drive

Cards

START Basic Front: Graph Valid Tree Back: Have the previous node in your recursive call so that you avoid having that node called within your adjacency list (i.e. 0 1 0).

END


References