🐌1. 题目描述
:::info 给定三个参数
- 二叉树的头节点head,
- 树上某个节点target,
- 正整数K
从target开始,可以向上走或者向下走,返回于target的距离是K的所有节点。 ::: 示例
💡2. 解决思路
- 从二叉树的指定节点target开始,既可以向上也可以向下走,说明需要对该二叉树结构进行功能增强,每个节点应该知道自己的父节点是谁,因此需要个结构保存每个节点的父节点信息的对应关系,这样达到一个无向图的效果。
- 然后基于增强功能的树结构,查找距离target节点长度为K的所有节点,图的宽度优先遍历(队列实现),找到第K层的所有节点就是输出答案。
- 为了方便输出某一层的所有的节点,对入队的一层的所有节点进行批处理操作。
- 为了避免节点重复入栈,需要设置一个Set集合,用于节点的注册,避免重复入栈。
🚩3. 代码实现
public class Code08_DistanceKNodes {// 二叉树结构public static class Node {public int value;public Node left;public Node right;public Node(int v) {value = v;}}public static List<Node> distanceKNodes(Node root, Node target, int K) {// 存储节点的父子关系HashMap<Node, Node> parents = new HashMap<>();// 头节点的父节点为nullparents.put(root, null);// 构建root二叉树的父子节点关系createParentMap(root, parents);// 队列用于实现宽度优先遍历Queue<Node> queue = new LinkedList<>();// 注册集合用于存放访问过的节点信息HashSet<Node> visited = new HashSet<>();// 基于二叉树结构和父子关系映射表map来实现从target节点开始的宽度优先遍历queue.offer(target); // target入队visited.add(target); // 将入队的注册到集合中int curLevel = 0;// 存放返回结果List<Node> ans = new ArrayList<>();while (!queue.isEmpty()) {// 当前层的节点个数int size = queue.size();// 对同层的节点进行同批处理while (size-- > 0) {Node cur = queue.poll();// 如果是K层则加入到结果中,K层表示距离为target节点距离为Kif (curLevel == K) {ans.add(cur);}if (cur.left != null && !visited.contains(cur.left)) {visited.add(cur.left);queue.offer(cur.left);}if (cur.right != null && !visited.contains(cur.right)) {visited.add(cur.right);queue.offer(cur.right);}if (parents.get(cur) != null && !visited.contains(parents.get(cur))) {visited.add(parents.get(cur));queue.offer(parents.get(cur));}}curLevel++;if (curLevel > K) {break;}}return ans;}/*** 递归创建父子对应关系* @param cur 当前节点* @param parents 存储指定父子节点的对应关系,key为子节点,value为父节点*/public static void createParentMap(Node cur, HashMap<Node, Node> 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);}}// 测试public static void main(String[] args) {Node n0 = new Node(0);Node n1 = new Node(1);Node n2 = new Node(2);Node n3 = new Node(3);Node n4 = new Node(4);Node n5 = new Node(5);Node n6 = new Node(6);Node n7 = new Node(7);Node n8 = new Node(8);n3.left = n5;n3.right = n1;n5.left = n6;n5.right = n2;n1.left = n0;n1.right = n8;n2.left = n7;n2.right = n4;Node root = n3;Node target = n5;int K = 2;List<Node> ans = distanceKNodes(root, target, K);for (Node o1 : ans) {System.out.println(o1.value);}}}
🔑4. 考点
二叉树遍历图的深度优先遍历
