1、题目描述
2、解题思路
如果题目这样说:从值为 k 的结点的子树中,找出距离它最近的叶子节点,相信所有人都能秒杀这道题,直接 BFS 即可。
本题的难点在于,它是从整棵树中找距离值为 k 的结点最近的叶子节点。它可能是这样的:
很明显,绿色的叶子节点就是距离 k 最近的那个。
我们的 BFS 原理是:处理好当前节点,则把它对其他节点的引用入队。
如果我们从节点 k 出发,按照二叉树的结构,是无法访问到图中绿色的节点。
因此,我们来修改二叉树的结构如下:
画的有点难看,其实就是把原来二叉树每个节点只能指向左右子结点改为增加指向父结点的指针。
这样,从节点 k 出发进行 BFS ,第一个遇到的叶子节点就是绿色的那个。
3、解题代码
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public int findClosestLeaf(TreeNode root, int k) {
Map<TreeNode, List<TreeNode>> graph = new HashMap();
dfs(graph, root, null);
Queue<TreeNode> queue = new LinkedList();
Set<TreeNode> seen = new HashSet();
// 找到值为 k 的节点,把它当成 bfs 的起点
for (TreeNode node : graph.keySet()) {
if (node != null && node.val == k) {
queue.add(node);
seen.add(node);
}
}
while (!queue.isEmpty()) {
TreeNode node = queue.poll();
if (node != null) {
if (graph.get(node).size() <= 1) {
return node.val;
}
for (TreeNode nei : graph.get(node)) {
if (!seen.contains(nei)) {
seen.add(nei);
queue.add(nei);
}
}
}
}
// while 里面一定有 return,这里只是让编译器通过
throw null;
}
/**
* 原来的 TreeNode 结构只有两个左右子结点索引
* 经过 dfs 函数后生成 graph,它是一个 Map,key 为 二叉树的任意一个 node,value 为它的左子节点、右子节点、父结点
* 需要把二叉树转为 graph 就是为了 BFS 用,因为不仅往左右子树走,还得往父结点走
*
* @param graph
* @param node
* @param parent
*/
public void dfs(Map<TreeNode, List<TreeNode>> graph, TreeNode node, TreeNode parent) {
if (node != null) {
if (!graph.containsKey(node)) graph.put(node, new LinkedList<TreeNode>());
if (!graph.containsKey(parent)) graph.put(parent, new LinkedList<TreeNode>());
graph.get(node).add(parent);
graph.get(parent).add(node);
dfs(graph, node.left, node);
dfs(graph, node.right, node);
}
}
}