[LeetCode] 二叉树中所有距离为 K 的结点

140 阅读2分钟

这是我参与2022首次更文挑战的第17天,活动详情查看:2022首次更文挑战

题目

863. 二叉树中所有距离为 K 的结点 - 力扣(LeetCode) (leetcode-cn.com)

解析

首先,要分析一下,和目标节点距离为K的节点,可能处于哪些位置?

  • 第一部分,最简单的:在目标节点之下的第K层节点。

    由于目标节点已给定,因此这部分是最好求得的:

public void searchForSub(TreeNode root, int k, List<Integer> res){
    if(root==null) return;
    if(k==0){
        res.add(root.val);
        return;
    }
    searchForSub(root.left,k-1,res);
    searchForSub(root.right,k-1,res);
}
  • 第二部分:目标节点之上的。

    这些节点和目标节点共享某一段相同的节点,此时需要知道:

    • 这些节点和目标节点,距离是多少。

      随后,从目标节点的路径的另一侧去取某一层的。

      此时同样地可以使用上面的方法,但是需要确定目标节点在哪一侧

对于第二部分,我们可以这么做:

  • 从根节点,往下进行遍历,每往下遍历一层,层数+1
    • 如果当前节点和给定的目标节点相同,那么就返回当前层数,这代表了目标节点到根节点距离是多少
    • 如果当前节点为null,那么返回-1,代表该分支上并没有目标节点。
  • 上层节点接收到了下层返回的值V。
    • 如果V不为-1,那么就代表这一层往下是能获取到目标节点的。
    • 此时,根据当前的层数L,V-L就代表了目标节点到当前节点距离是多少。
    • 根据目标节点所在的分支(假设为),求取当前节点的另一分支往下L-V层的所有节点,添加到结果之中。
      • 这里需要注意,如果V-L=K,这代表当前节点到目标节点距离就是K,此时把当前节点塞到结果中,返回即可。

根据上述思路,拟代码如下:

public List<Integer> distanceK(TreeNode root, TreeNode target, int k) {
    List<Integer> res = new ArrayList<>();
    searchForSub(target,k,res);
    findTarget(root,target,0,k,res);
    return res;
}

public void searchForSub(TreeNode root, int k, List<Integer> res){
    if(root==null) return;
    if(k==0){
        res.add(root.val);
        return;
    }
    searchForSub(root.left,k-1,res);
    searchForSub(root.right,k-1,res);
}

public int findTarget(TreeNode root,TreeNode target,int cur,int k,List<Integer> res){
    if(root == null) return -1;
    if(root == target) return cur;
    int l = findTarget(root.left,target,cur+1,k,res);
    if(l!=-1){
        int t = l-cur;
        if(t==k){
            res.add(root.val);
            return l;
        }
        t++;
        searchForSub(root.right,k-t,res);
        return l;
    }else{
        int r = findTarget(root.right,target,cur+1,k,res);
        if(r!=-1){
            int t = r - cur;
            if(t == k){
                res.add(root.val);
                return r;
            }
            t++;
            searchForSub(root.left,k-t,res);
        }
    }
    return -1;
}

结果:

执行用时:9 ms, 在所有 Java 提交中击败了100.00%的用户

内存消耗:41.3 MB, 在所有 Java 提交中击败了8.74%的用户