← 返回题目列表

二叉树中如何找距离目标节点 K 的所有节点?为什么要把树看成无向图?

中等 第 23 / 30 题 更新于 2026/07/30
二叉树距离 K父指针BFS

简化版

找距离目标节点 K 的节点时,路径可能向下走到子节点,也可能向上走到父节点。因此常先建立 parent 映射,把二叉树看成无向图,再从 target 做 BFS 扩展 K 层。

详细版

普通二叉树节点只有左右孩子指针,不能直接往父节点走。但距离 K 的路径不限制方向。

做法:

  • DFS 遍历整棵树,记录 parent[child] = node
  • 从 target 开始 BFS。
  • 每个节点的邻居是 left、right、parent。
  • 用 visited 防止从父子之间来回走。
  • BFS 扩展到第 K 层,当前队列里的节点就是答案。

时间复杂度 O(n),空间 O(n)。关键是把树的有向父子关系补成可双向行走的图。

完整版教学

一、为什么只向下 DFS 不够

如果目标节点在左子树,距离 K 的节点可能在它的子树里,也可能经过父节点走到兄弟子树。

      1
     / \
    2   3
   /
  4
target = 2, K = 2

距离 2 的节点包括 3,路径是 2 -> 1 -> 3。这条路径需要先向上到父节点,再向下到兄弟节点。只沿 left/right 向下走找不到。

二、为什么要建立 parent 映射

普通二叉树节点没有 parent 指针。为了从 target 向上走,需要提前记录每个节点的父节点。

function buildParent(node, parent) {
  if (!node) return;
  parentMap.set(node, parent);
  buildParent(node.left, node);
  buildParent(node.right, node);
}

这样每个节点的邻居就从两个孩子扩展成最多三个方向:left、right、parent。

三、为什么要看成无向图

树本身也是一种无环连通图。补上 parent 后,任意相邻父子节点都可以双向走。

node 的邻居:
left child
right child
parent

从 target 出发找距离 K,其实就是图上的 BFS 最短距离问题。BFS 每扩展一层,距离就加 1;扩展 K 层后正好得到距离 K 的所有节点。

四、visited 为什么必须有

补上 parent 后,边变成双向。如果不记录 visited,会在父子之间来回走。

2 -> 1 -> 2 -> 1 ...

visited 保证每个节点只入队一次。树没有环,但当你把父子边当成双向边后,来回走就是图搜索中的重复访问问题。

五、BFS 层数怎么控制

可以把队列按层处理。初始 target 是第 0 层,每扩展一轮距离加 1。当距离等于 K 时,队列中所有节点就是答案。

dist=0: target
dist=1: target 的邻居
dist=2: 邻居的未访问邻居

如果 K=0,答案就是 target 本身。这个边界要提前处理或让 BFS 自然支持。

六、复杂度和变体

建立 parent 映射 O(n),BFS 最坏访问所有节点 O(n),总时间 O(n),空间 O(n)。如果节点本身有 parent 指针,就可以省掉建表阶段。

方案思路复杂度特点
parentMap + BFS先补父指针,再从 target 扩散直观,时间 O(n)、空间 O(n)
递归返回距离自底向上找 target 并处理兄弟子树空间可少一些,但逻辑更绕
节点自带 parent直接把树当无向图 BFS省掉建 parentMap

记忆钩子:距离 K 不是“往下 K 层”,而是“从 target 走 K 条边”;能往父节点走后,树就变成无向图 BFS。

七、常见误区与追问

  • 误区:距离 K 只需要搜索 target 的子树。 目标节点的父方向和兄弟子树也可能有答案。
  • 误区:树没有环,所以 BFS 不需要 visited。 加了 parent 后会在父子之间来回走,必须 visited。
  • 误区:K=0 返回空。 K=0 时距离目标 0 的节点就是目标节点。
  • 追问:没有 target 引用只有 target 值怎么办? 先遍历找到目标节点,再 BFS。
  • 追问:能不用 parentMap 吗? 可以递归返回距离并处理兄弟子树,但逻辑更复杂;图化 BFS 更直观。

八、加强记忆

这题的关键转换是“树题变图题”。只向下不是距离,能沿父子边双向走才是距离。先建 parent,再从 target 做 BFS,扩展 K 层即可;visited 是防止双向边反复走的保险。