LeetCode All Nodes Distance K in Binary Tree

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/sun_wangdong/article/details/82934218

给定一个二叉树(具有根结点 root), 一个目标结点 target ,和一个整数值 K 。

返回到目标结点 target 距离为 K 的所有结点的值的列表。 答案可以以任何顺序返回。

示例 1:

输入:root = [3,5,1,6,2,0,8,null,null,7,4], target = 5, K = 2

输出:[7,4,1]

解释:
所求结点为与目标结点(值为 5)距离为 2 的结点,
值分别为 7,4,以及 1



注意,输入的 "root" 和 "target" 实际上是树上的结点。
上面的输入仅仅是对这些对象进行了序列化描述。
提示:
  1. 给定的树是非空的,且最多有 K 个结点。
  2. 树上的每个结点都具有唯一的值 0 <= node.val <= 500 。
  3. 目标结点 target 是树上的结点。
  4. 0 <= K <= 1000.

题解,给定一棵二叉树、一个目标节点和一个目标值k,要求给出距离该目标节点距离为k的所有节点的值,保存在一个list中,返回。拿到这道题,一开始lz有点懵,不知道该从何下手,后来结合一些网上的资料,有了一些想法,可以将给定的目标节点想成是现有的“根节点”,那么就从该“根节点”出发,去遍历,其中它的第一圈就是它的父节点和子节点,类似于层次遍历;然后遍历第二层就是距离该目标节点距离为2的节点层;以此类推,最终到达距离该目标节点距离为k的所有节点,将它们都保存在list中存储。那么可以构造成一棵新的树,如下所示:

上述原始的二叉树就变为新的一棵多叉树,其中以目标节点为根节点,以距离它最近的父节点和左右子节点为它的第一层节点,后面层的节点以此类推;那么就如同用层次遍历的方式来控制距离它k的那层,将那层节点全部输出即可。

public void setParentTreeNode(TreeNode root,Map<TreeNode,TreeNode> parentTreeNodeMap,TreeNode parent)
    {      //这个函数用来求得原始二叉树的每个节点的父节点,并将它们用一个hashmap来保存
        if(root == null)
            return;
        if(parent != null)
            parentTreeNodeMap.put(root,parent);
        setParentTreeNode(root.left,parentTreeNodeMap,root);
        setParentTreeNode(root.right,parentTreeNodeMap,root);
    }
    public List<Integer> distanceK(TreeNode root,TreeNode target,int K)
    {
        List<Integer> retList = new ArrayList<>();
        Map<TreeNode,TreeNode> parentsTreeMap = new HashMap<>();
        setParentTreeNode(root,parentsTreeMap,null);   //记录下二叉树中所有节点的父节点

        Queue<TreeNode> checkQueue = new LinkedList<>();     
        checkQueue.add(target);
        Set<TreeNode> hasCheck = new HashSet<>();
        hasCheck.add(target);
        while(!checkQueue.isEmpty() && K > 0)  //用K来记录层次遍历的层数
        {
            K--;
            int size = checkQueue.size();     //在每遍历一层时,都要先记录该层的节点数
            for(int i = 0; i < size; i++)
            {
                TreeNode treeNode = checkQueue.poll();
                if(treeNode.left != null && !hasCheck.contains(treeNode.left))
                {
                    checkQueue.add(treeNode.left);
                    hasCheck.add(treeNode.left);
                }
                if(treeNode.right != null && !hasCheck.contains(treeNode.right))
                {
                    checkQueue.add(treeNode.right);
                    hasCheck.add(treeNode.right);
                }
                if(parentsTreeMap.containsKey(treeNode) && !hasCheck.contains(parentsTreeMap.get(treeNode)))
                {
                    hasCheck.add(parentsTreeMap.get(treeNode));
                    checkQueue.add(parentsTreeMap.get(treeNode));
                }
            }
        }
        while(!checkQueue.isEmpty())   //当k为0时,那么就表明已经到达了所需要的那一层了
            retList.add(checkQueue.poll().val);  //将距离目标节点距离为k的所有节点输出
        return retList;
    }

通过上述代码实现,可以有所收获:

1、可以用一个递归函数,通过hashmap的方式来获取每个节点的父节点

2、重新将原始二叉树进行重排,以所需要找的目标节点为新的“根节点”,去遍历每一层,其中第一层,即距离该目标节点距离为1的层,为目标节点在原二叉树中的父节点和它的左右子节点;然后将该父节点和左右子节点压入队列中,再扫描第二层,即距离该目标节点距离为2的节点,以此类推,直到找到距离该目标节点距离为k为止。

该方法很巧妙!值得好好揣摩!

猜你喜欢

转载自blog.csdn.net/sun_wangdong/article/details/82934218