在问 · 算法题解

133. 克隆图

中等图论哈希表+BFS力扣原题 ↗

题目描述

输入一张无向连通图中某个节点的引用。每个节点含整数值 val 和邻居节点列表 neighbors。返回整张图的深拷贝:新图的每个节点都要新建,结构与原图一致。

测试数据用邻接表描述图。节点值从 1 开始编号,邻接表第 i 个列表(从 0 数)列出值为 i + 1 的节点的邻居。

传入的节点总是值为 1 的节点。你需要返回它对应的新节点。输出同样以邻接表展示;图为空时输出 []。

示例 1
输入:edges = [[2,4],[1,3],[2,4],[1,3]]
输出:[[2,4],[1,3],[2,4],[1,3]]

解释:4 个节点连成一个环 1-2-3-4-1,拷贝后邻接表相同。

示例 2
输入:edges = [[]]
输出:[[]]

解释:只有一个值为 1 的节点,没有邻居。

示例 3
输入:edges = []
输出:[]

解释:图中没有节点。

数据范围

  • 节点数在 [0, 100] 之间。
  • 1 <= Node.val <= 100
  • 各节点的值互不相同。
  • 没有重边,也没有连向自己的边。
  • 图是连通的,从给定节点能到达所有节点。

解题思路:哈希表+BFS

用哈希表 clones 记录“原节点 → 新节点”。BFS 遍历原图:弹出 cur,枚举它的每个邻居 nb;如果 nb 还没克隆,就新建并入队;然后把 clones[nb] 接到 clones[cur] 的邻居列表里。哈希表同时起到“已访问”的作用。

为什么正确

一个原节点恰好对应一个克隆节点;一个节点出队处理完后,它的克隆的邻居列表就与原节点一一对应。

复杂度分析

时间 O(V + E),空间 O(V)。

易错点

必须先把新节点放进哈希表,再处理它的邻居;否则遇到环时会把同一个节点克隆多次。另外,新节点的邻居必须指向克隆节点,不能指回原图。空图要返回 null。

参考代码

Python、Java、C++、Go、JavaScript、TypeScript 六种语言,逻辑一致。

class Solution:
    def cloneGraph(self, node: Optional['Node']) -> Optional['Node']:
        if not node:
            return None
        clones = {node: Node(node.val)}
        queue = collections.deque([node])
        while queue:
            cur = queue.popleft()
            for nb in cur.neighbors:
                if nb not in clones:
                    clones[nb] = Node(nb.val)
                    queue.append(nb)
                clones[cur].neighbors.append(clones[nb])
        return clones[node]

载入编辑器,自己跑一遍 →

其他解法

两种解法都用哈希表防止重复克隆,复杂度相同;DFS 更简洁,BFS 不受递归深度限制。

解法 2:哈希表+DFS 时间 O(V+E),空间 O(V)

用哈希表记录原节点到克隆节点的映射。递归访问节点时,若已克隆就直接返回克隆节点。否则先创建克隆节点并登记,再递归克隆每个邻居并加入邻居列表。

代码更短,节点和邻居的关系一目了然。递归深度可达节点数,图很大时可能栈溢出。

import sys
from typing import Optional

class Solution:
    def cloneGraph(self, node: Optional['Node']) -> Optional['Node']:
        sys.setrecursionlimit(10000)
        clones = {}

        def dfs(cur):
            if cur in clones:
                return clones[cur]
            copy = Node(cur.val)
            clones[cur] = copy
            for nb in cur.neighbors:
                copy.neighbors.append(dfs(nb))
            return copy

        return dfs(node) if node else None

图论 专题的其他题目

查看 图论 全部题目 →