133. Clone Graph
MediumDescription
給定一個無向連通圖中某個節點的參考,回傳該圖的深拷貝 (deep copy)。每個節點包含一個值和一個鄰居列表。
Example:
Input: adjList = [[2,4],[1,3],[2,4],[1,3]] Output: [[2,4],[1,3],[2,4],[1,3]]
Intuition#
用 HashMap 記錄「原始節點 -> 複製節點」的映射,遍歷圖時遇到已複製的節點直接回傳映射。
- 深拷貝圖的關鍵是避免重複建立節點(圖可能有環)
- 使用 HashMap 紀錄已複製的節點,同時充當 visited 的角色
- DFS 或 BFS 皆可,差異只在遍歷順序
Approaches#
1: BFS#
- 概念: 從起始節點開始 BFS,每次出隊時建立鄰居的複製品並連接
- 時間複雜度:
O(V + E) - 空間複雜度:
O(V)
class Solution {
fun cloneGraph(node: Node?): Node? {
if (node == null) return null
val map = HashMap<Node, Node>()
val queue: ArrayDeque<Node> = ArrayDeque()
map[node] = Node(node.`val`)
queue.add(node)
while (queue.isNotEmpty()) {
val cur = queue.removeFirst()
for (neighbor in cur.neighbors) {
if (neighbor != null && neighbor !in map) {
map[neighbor] = Node(neighbor.`val`)
queue.add(neighbor)
}
map[cur]!!.neighbors.add(map[neighbor])
}
}
return map[node]
}
}⭐2: DFS(遞迴)#
- 概念: 遞迴訪問每個節點,利用 HashMap 避免重複訪問並建立映射關係
- 時間複雜度:
O(V + E) - 空間複雜度:
O(V)
class Solution {
private val map = HashMap<Node, Node>()
fun cloneGraph(node: Node?): Node? {
if (node == null) return null
if (node in map) return map[node]
val clone = Node(node.`val`)
map[node] = clone
for (neighbor in node.neighbors) {
clone.neighbors.add(cloneGraph(neighbor))
}
return clone
}
}🔑 Takeaways#
- Pattern: 圖的深拷貝 – HashMap 映射 + DFS/BFS 遍歷
- 關鍵技巧: HashMap 同時解決「是否已訪問」和「原始到複製的映射」兩個問題