LeetCode 133 Clone Graph:题目回顾
Clone Graph 是什么题?LeetCode 133:给定一个无向连通图中的某个节点引用,每个节点有一个整数值 val 和一个邻居列表 neighbors,要求返回整张图的深拷贝(克隆图),返回值是「克隆后图中对应起始节点」的指针。
题目保证
- 图是无向且连通
- 最多 100 个节点
- 没有重边和自环
- 任意节点可以通过若干条边到达其他所有节点
这本质上是:给你一张可能有环的无向连通图,让你构造一张结构完全相同、但节点对象全部重新 new 出来的图。
直观思路:DFS 克隆图 + 哈希表
直觉做法很自然:从起点出发遍历整张图,一边遍历一边「克隆当前节点,并克隆所有邻居关系」。主流推荐解法是 DFS/BFS + 哈希表,核心是两点:
- 遍历方式:可以用 DFS(递归)或 BFS(队列),两种都行,只是访问顺序不同,本质工作是一致的。
- 必须有一个「原节点 → 新节点」的映射表(哈希表 / 字典),来记住每个原节点已经克隆出的副本。
典型的 DFS 思路
设计函数 Node* dfs(Node* node):返回 node 在克隆图里的对应节点指针。
进入 dfs(node) 时:
- 如果 node 已经在 map 里,说明之前克隆过了,直接返回 map 中的克隆节点,避免重复克隆和无限递归。
- 否则,新建一个
Node* clone = new Node(node->val),先把 clone 存到 map 中(关键:先存,再递归),然后遍历node->neighbors,对每个邻居递归dfs(v),把返回的克隆邻居推入clone->neighbors。
外层 cloneGraph 调用:
- 处理 null 输入的特例。
- 初始化 map,然后从起始节点调用
dfs(start)并返回结果。
最大的坑点:图中有环
如果没有 map,而是无脑递归,每次遇到邻居都 new 一个新节点,你会陷入两类问题:
- 图有环会无限递归,栈溢出。
- 即使能停下来,同一个逻辑节点会被克隆出多个副本,结构已经和原图不一致。
面试官常见的引导方式就是:先肯定你「递归克隆 + 遍历邻居」的想法,然后追问「图里有环会怎样?」「同一个节点被多条路径访问时,你会不会 new 出好几个副本?」来逼你补出这张哈希表。
时间复杂度分析:O(N + E)
这道题的时间复杂度通常写成 O(N + E),其中 N 是节点数(顶点数),E 是边数。
从「遍历图」的角度理解
- 每个节点最多被 DFS/BFS「正式处理」一次:因为一旦访问过就会标记在 map / visited 里,以后再遇到直接复用结果,不再深入。这部分代价是 O(N)。
- 每条边恰好在遍历它两端节点的邻接表时被「看」到一次:用邻接表存图时,总共遍历所有节点的邻接表一遍,整体访问次数与边数同阶,因此这部分是 O(E)。
把两部分加起来就是 O(N + E)。这和普通的 DFS / BFS 在图上的复杂度是同一个结论,只不过这里遍历时的「访问动作」变成了「克隆节点 + 接上邻居」。
空间复杂度
- 用一个 map 存每个节点的克隆结果,需要 O(N) 空间。
- 邻接表本身是输入给出的,不计入额外空间;递归 DFS 的调用栈最坏深度为 O(N),因此总体额外空间也是 O(N)。
无向连通图 vs 有向连通图
Clone Graph 这道题里强调的是「无向且连通图」,这一点对遍历策略和正确性有直接影响。
在图论中
无向图:每条边没有方向,(u,v) 和 (v,u) 等价,表示可以双向走;通常用「邻接表」或「邻接矩阵」存储时,一条边会在两个端点的邻接结构中都出现一次。
无向连通图:任意两个顶点之间存在至少一条路径,否则就是不连通,会被分解为多个连通分量;从任意一个节点开始做一次 DFS/BFS,就能访问整张图。
而有向图中,「连通」要细分为几种情形:
- 强连通(strongly connected):对任意两个点 u, v,既能顺着边从 u 到 v,也能从 v 到 u。
- 弱连通(weakly connected):如果把所有有向边都当成无向边(忽略方向),得到的无向图是连通的,就叫弱连通。
这两个概念的差别在于:是否要求方向上「互相可达」。强连通相当于「在保持方向的前提下,任意两点都互相 reachable」,弱连通只要求把方向抹掉之后图是一整块。
对算法的影响
对无向连通图:从任意起点一次 DFS/BFS 一定能遍历所有节点,这就是 Clone Graph 能假定「只给你一个起点,整张图都能从它访问到」的理由。
对有向图:如果图不是强连通,从一个起点出发的 DFS/BFS 只能覆盖和它所在强连通分量相连的那些点,可能无法访问整张图;这时如果题目要你克隆「整张图」,就不能只从一个点出发,而要对所有未访问的节点多次启动遍历。强连通分量(SCC)算法就是基于这一性质设计的。
在 Clone Graph 这种「无向且连通」的设定下,问题被大大简化:只要从给定节点做一次 DFS/BFS 克隆即可,不用担心有孤立点或者多个连通块。
总体价值
这道题的价值主要在三个点:
- 理解图的连通性与遍历
- 在有环结构上做「深拷贝」时一定要用「旧对象 → 新对象」映射
- 把 DFS/BFS 的复杂度直观理解成 O(N + E)
这些概念在后面做图论、克隆复杂结构对象、或者处理强连通分量等问题时都会反复出现。

143

被折叠的 条评论
为什么被折叠?



