【LeetCode - 742】二叉树最近的叶节点

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);
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值