/** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode(int x) { val = x; } * } */ classSolution{ List<Integer> result; int k;
public List<Integer> distanceK(TreeNode root, TreeNode target, int K){ result = new ArrayList<>(); k = K; dfs(root, target); return result; }
publicintdfs(TreeNode cur, TreeNode target){ if (cur == null) { return -1; // 返回-1表示在当前子树没有找到目标节点 } if (cur == target) { subtreeAdd(cur, 0); // 找到目标节点了,对目标节点子树进行查找 return1; // 返回他的父节点到目标节点距离 } else { int d = dfs(cur.left, target); if (d != -1) { // 目标节点在左子树 if (d == k) { // 当前节点符合到目标节点距离,添加到结果集 result.add(cur.val); } subtreeAdd(cur.right, d + 1); // 寻找当前节点右子树符合条件的节点 return d + 1; // 返回当前节点父节点到目标节点的距离 } else { d = dfs(cur.right, target); if (d != -1) { // 目标节点在右子树 if (d == k) { // 当前节点符合到目标节点距离,添加到结果集 result.add(cur.val); } subtreeAdd(cur.left, d + 1); // 寻找当前节点左子树符合条件的节点 return d + 1; // 返回当前节点父节点到目标节点的距离 } } return -1; // 目标节点在当前子树不存在 } }
// 查找当前子树符合到目标节点距离的值,保存结果 publicvoidsubtreeAdd(TreeNode cur, int d){ if (cur == null || d > k) { return; } if (k == d) { result.add(cur.val); } subtreeAdd(cur.left, d + 1); subtreeAdd(cur.right, d + 1); } }
/** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode(int x) { val = x; } * } */ classSolution{
public List<Integer> distanceK(TreeNode root, TreeNode target, int K){ Map<TreeNode, TreeNode> child2parent = new HashMap<>(); dfs(root, null, child2parent); // 建立子节点到父节点的映射
Queue<TreeNode> queue = new LinkedList<>(); queue.offer(target); queue.offer(null); // 以null为到目标节点距离相同的节点集分割点
HashSet<TreeNode> seen = new HashSet<>(); // 标记查找过的节点,保证入队节点距离目标节点的距离是逐渐增加的 seen.add(target); seen.add(null);
List<Integer> result = new ArrayList<>(); // 保存结果 while (!queue.isEmpty()) { TreeNode tmp; if (K == 0) { // 到目标节点距离为K,将当前队列中所有节点集保存到结果,null节点是分割点 while ((tmp = queue.poll()) != null) { result.add(tmp.val); } } else { while ((tmp = queue.poll()) != null) { // 遍历当前距离目标节点距离相等的所有节点,分别将他的父节点、左子节点、右子节点 // 入队(如果这些节点没有被标记过,即他们离目标节点的距离都是+1) if (!seen.contains(tmp.left)) { seen.add(tmp.left); queue.offer(tmp.left); } if (!seen.contains(tmp.right)) { seen.add(tmp.right); queue.offer(tmp.right); } if (!seen.contains(child2parent.get(tmp))) { seen.add(child2parent.get(tmp)); queue.offer(child2parent.get(tmp)); } } queue.offer(null); // null入队分割下次循环 K--; // 目标距离-1 } } return result; } publicvoiddfs(TreeNode cur, TreeNode parent, Map<TreeNode, TreeNode> child2parent){ if (cur != null) { child2parent.put(cur, parent); dfs(cur.left, cur, child2parent); dfs(cur.right, cur, child2parent); } } }
给定一个有 N 个结点的二叉树的根结点 root,树中的每个结点上都对应有 node.val 枚硬币,并且总共有 N 枚硬币。在一次移动中,我们可以选择两个相邻的结点,然后将一枚硬币从其中一个结点移动到另一个结点。(移动可以是从父结点到子结点,或者从子结点移动到父结点。)。返回使每个结点上只有一枚硬币所需的移动次数。