这是我参与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%的用户