I am trying to solve LeetCode problem 133. Clone Graph:
Given a reference of a node in a connected undirected graph.
Return a deep copy (clone) of the graph.
Each node in the graph contains a value (
int) and a list (List[Node]) of its neighbors.class Node { public int val; public List<Node> neighbors; }Test case format:
For simplicity, each node's value is the same as the node's index (1-indexed). For example, the first node with
val == 1, the second node withval == 2, and so on.
I used a DFS traversal to do a deep copy along the way, but it is not getting accepted. I tried printing out the node values and its memory addresses of the original and copy, side by side, and I don't understand why my deep copy wouldn't pass as a working solution. I commented out the unnecessary lines for testing.
"""
# Definition for a Node.
class Node:
def __init__(self, val = 0, neighbors = None):
self.val = val
self.neighbors = neighbors if neighbors is not None else []
"""
from typing import Optional
class Solution:
def cloneGraph(self, node: Optional['Node']) -> Optional['Node']:
if not node:
return
if not node.neighbors:
return Node(node.val)
ans = Node(node.val,[])
visited = set()
def dfs(node,copy):
if not node or node.val in visited:
return
visited.add(node.val)
neighbors = node.neighbors
for neighbor in neighbors:
deepcopy = Node(neighbor.val)
copy.neighbors.append(deepcopy)
dfs(neighbor,deepcopy)
dfs(node,ans)
# test = set()
# def dfsTest(og,copy):
# if og in test:
# return
# test.add(og)
# og_n = og.neighbors
# copy_n = copy.neighbors
# for o,c in zip(og_n,copy_n):
# print(o,c)
# print(o.val,c.val)
# dfsTest(o,c)
# dfsTest(node,ans)
return ans
The problem is that your code cannot produce a graph that has cycles. Yet this must be supported, because the input graph can have cycles, and it is for those test cases your code will fail.
It creates a new Node (
deepcopy) for a neighbor, even if that neighbor was already visited. In that case, you had already created a copy for the (neighbor) node, and you should reuse it at this point instead of creating yet another copy.To achieve that, I would suggest turning
visitedinto a dictionary, so that when you detect that a node was already visited, you can also retrieve the copy that was created for it.Unrelated remarks
dfs. Instead let it return the copied node.dfswill deal with those just fine.Correction
Here is a correction of your code that implements that idea:
You can shorten this code a bit by using
map()and combining two cases with onereturn: