目录
题目描述
给定一个二叉树(具有根结点 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
示例 2:
输入: root = [1], target = 1, k = 3 输出: []
分析题意
本题题目已经描述的很清楚就是找到target离它K距离的节点有哪些.
对于5这个节点距离为k的节点为 1,7,4 这三个节点.
解题思路
首先这道题是 图 + BFS(广度优先遍历)来做
其实不知道什么是图也无所谓.你想一想我们既然要找到一个节点距离为k的节点,有可能这个节点在他上面的那条路线,也有可能是在他下面的路线,对于下面的路线很好说,关键对于二叉树而言只能往下走,所以就需要建立一张父表,也就是对于每一个节点我都用一个哈希表来存放他们的父亲节点,这样就可以往上走了.
既然有了父表,接下来该如何做呢.
- 从target出发开始进行遍历,除了要遍历左孩子和右孩子外,还要遍历父亲节点的那条通道
- 每一层都要对其左孩子,右孩子,父亲节点遍历,当遍历到第k层就进行收集答案,也就找到了距离为k的节点
对于上面的过程我使用队列来进行模拟也就是广度优先搜索,由于遍历过的节点不能在往队列里面放入了,所以还要加一个HashSet.
代码详解
- 如何给每一个节点在哈希表中添加父节点呢
//parents<孩子节点,父节点>
public static void createParentMap(TreeNode cur, HashMap<TreeNode, TreeNode> parents){
if(cur==null){
return;
}
if(cur.left!=null){//左孩子的父亲就是cur
parents.put(cur.left,cur);
createParentMap(cur.left,parents);//左树递归去
}
if(cur.right!=null){//右孩子的父亲就是cur
parents.put(cur.right,cur);
createParentMap(cur.right,parents);//右树递归去
}
}
整体代码
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
//对于target节点找到二叉树中距离k的节点有哪些,使用list返回
//对于target节点找到二叉树中距离k的节点有哪些,使用list返回
public static List<Integer> distanceK(TreeNode root, TreeNode target, int k){
//生成一个父亲表 能够让节点往上走
HashMap<TreeNode, TreeNode> parents = new HashMap<>();
parents.put(root,null);
createParentMap(root,parents);
Queue<TreeNode> queue = new LinkedList<>();
HashSet<TreeNode> visited = new HashSet<>();//被访问过得节点不能在加入到队列中
//刚开始从target出发
queue.offer(target);
visited.add(target);
int curLevel = 0;//当前层数
List<Integer> ans = new ArrayList<>();//收集答案
while(!queue.isEmpty()){
int size = queue.size();
while(size-->0){
TreeNode cur = queue.poll();
if(curLevel==k){//为k层收集答案
ans.add(cur.val);
}
if(cur.left!=null && !visited.contains(cur.left)){//左孩子不为空,左孩子没有被访问过
queue.offer(cur.left);
visited.add(cur.left);
}
if(cur.right!=null && !visited.contains(cur.right)){//右孩子不为空,右孩子没有被访问过
queue.offer(cur.right);
visited.add(cur.right);
}
if(parents.get(cur)!=null && !visited.contains(parents.get(cur))){//父亲节点不为空,父亲节点没有被访问过
queue.offer(parents.get(cur));
visited.add(parents.get(cur));
}
}
curLevel++;
if(curLevel>k){//已经收集完答案了返回
break;
}
}
return ans;
}
//parents<孩子节点,父节点>
public static void createParentMap(TreeNode cur, HashMap<TreeNode, TreeNode> parents){
if(cur==null){
return;
}
if(cur.left!=null){
parents.put(cur.left,cur);
createParentMap(cur.left,parents);
}
if(cur.right!=null){
parents.put(cur.right,cur);
createParentMap(cur.right,parents);
}
}
}