给定一个二叉树的根节点 root ,和一个目标节点的值 target ,和一个目标距离 k ,请你找出二叉树上所有与 target 距离是 k 的节点的值。
数据范围:二叉树的节点数满足
,节点上的值在范围 [0,n) 内,每个节点的值各不相同。 
import java.util.*;
// 以节点target 为根, 下面第k层节点
// 以节点target 父节点 为根, 下面第k-1层节点
// 父父节点, k-2层 ... 循环
//
// Map存父节点
public class Solution {
ArrayList<Integer> res = new ArrayList<>(); // 结果
Set<TreeNode> parent = new HashSet<>(); // target及父节点
public ArrayList<Integer> distanceKnodes (TreeNode root, int target, int k) {
// BFS: 找到target节点及其父节点
Map<TreeNode, TreeNode> map = new HashMap<>(); // 存父节点
map.put(root, null);
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root);
TreeNode targetNode = null; // target节点
while (!queue.isEmpty()) {
TreeNode t = queue.poll();
if (t.val == target) {
targetNode = t;
break;
}
if (t.left != null) {
map.put(t.left, t);
queue.offer(t.left);
}
if (t.right != null) {
map.put(t.right, t);
queue.offer(t.right);
}
}
// target及父节点
TreeNode p = targetNode;
while (p != null) {
parent.add(p);
p = map.get(p);
}
// 循环:target节点为根 下面k层节点, 父 k-1, 父父 k-2...
if (k == 0) res.add(target); // k==0 特判target
p = targetNode;
while (p != null) {
bfs(p, k, target); // 调用
p = map.get(p);
k--;
}
return res;
}
// BFS: 以root为根, 下面第k层节点 (排除target及其父节点那侧子树🍓)
void bfs(TreeNode root, int k, int target) {
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root);
int level = 0;
while (!queue.isEmpty() && level <= k + 1) {
level++;
int size = queue.size();
while (size-- > 0) {
TreeNode t = queue.poll();
if (level == k + 1) { // 下面第k层节点
res.add(t.val);
}
// 排除target及其父节点 那个子树分支(因为会重复计算,上去时已算过一部分路径了)
if (t.left != null && !parent.contains(t.left)) queue.offer(t.left);
if (t.right != null && !parent.contains(t.right)) queue.offer(t.right);
}
}
}
} import java.util.*;
/*
* public class TreeNode {
* int val = 0;
* TreeNode left = null;
* TreeNode right = null;
* public TreeNode(int val) {
* this.val = val;
* }
* }
*/
/**
* NC370 距离是K的二叉树节点
* @author d3y1
*/
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param root TreeNode类
* @param target int整型
* @param k int整型
* @return int整型一维数组
*/
public ArrayList<Integer> distanceKnodes (TreeNode root, int target, int k) {
// return solution1(root, target, k);
return solution2(root, target, k);
}
private HashSet<Integer>[] adj;
private boolean[] isVisited;
private ArrayList<Integer> result = new ArrayList<>();
private final int N = 1000;
/**
* 后序遍历 + 层序遍历
*
* 图模型
*
* @param root
* @param target
* @param k
* @return
*/
private ArrayList<Integer> solution1(TreeNode root, int target, int k){
isVisited = new boolean[N];
adj = new HashSet[N];
for(int i = 0; i < N; i++){
adj[i] = new HashSet<>();
}
postOrder(root);
levelOrder(target, k);
return result;
}
/**
* 递归: 后序遍历
* @param root
*/
private void postOrder(TreeNode root){
if(root == null){
return;
}
postOrder(root.left);
postOrder(root.right);
if(root.left != null){
adj[root.val].add(root.left.val);
adj[root.left.val].add(root.val);
}
if(root.right != null){
adj[root.val].add(root.right.val);
adj[root.right.val].add(root.val);
}
}
/**
* 队列: 层序遍历
* @param target
* @param k
*/
private void levelOrder(int target, int k){
Queue<Integer> queue = new LinkedList<>();
isVisited[target] = true;
queue.offer(target);
int curr;
int size;
int level = 0;
boolean isFound = false;
while(!queue.isEmpty()){
level++;
size = queue.size();
while(size-- > 0){
curr = queue.poll();
for(int next: adj[curr]){
if(!isVisited[next]){
isVisited[next] = true;
if(level == k){
isFound = true;
result.add(next);
}else{
queue.offer(next);
}
}
}
}
if(isFound){
break;
}
}
}
//////////////////////////////////////////////////////////////////////////////////////////
private ArrayList<Integer> list = new ArrayList<>();
private HashMap<Integer,TreeNode> parentMap = new HashMap<>();
/**
* 层序遍历 + 前序遍历
* @param root
* @param target
* @param k
* @return
*/
private ArrayList<Integer> solution2(TreeNode root, int target, int k){
if(root == null){
return list;
}
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root);
parentMap.put(root.val, null);
TreeNode node,cNode,pNode;
while(!queue.isEmpty()){
node = queue.poll();
if(node.val == target){
if(k == 0){
list.add(node.val);
return list;
}
downKnodes(node, k);
cNode = node;
pNode = parentMap.get(cNode.val);
while(pNode!=null && k>0){
upKnodes(cNode, pNode, --k);
cNode = pNode;
pNode = parentMap.get(cNode.val);
}
return list;
}
if(node.left != null){
parentMap.put(node.left.val, node);
queue.offer(node.left);
}
if(node.right != null){
parentMap.put(node.right.val, node);
queue.offer(node.right);
}
}
return list;
}
/**
* 向上遍历
* @param cNode
* @param pNode
* @param k
*/
private void upKnodes(TreeNode cNode, TreeNode pNode, int k){
if(k == 0){
list.add(pNode.val);
return;
}
if(pNode.left!=null && pNode.left.val!=cNode.val){
downKnodes(pNode.left, k-1);
}
if(pNode.right!=null && pNode.right.val!=cNode.val){
downKnodes(pNode.right, k-1);
}
}
/**
* 向下遍历
* @param root
* @param k
*/
private void downKnodes(TreeNode root, int k){
preOrder(root, k);
}
/**
* 前序遍历
* @param root
* @param k
*/
private void preOrder(TreeNode root, int k){
if(root == null){
return;
}
if(k == 0){
list.add(root.val);
return;
}
preOrder(root.left, k-1);
preOrder(root.right, k-1);
}
} import java.util.*;
/*
* public class TreeNode {
* int val = 0;
* TreeNode left = null;
* TreeNode right = null;
* public TreeNode(int val) {
* this.val = val;
* }
* }
*/
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param root TreeNode类
* @param target int整型
* @param k int整型
* @return int整型ArrayList
*/
public ArrayList<Integer> distanceKnodes(TreeNode root, int target, int k) {
// write code here
if (root == null) {
return new ArrayList<>();
}
// 最终返回的结果
Set<Integer> finalRes = new HashSet<>();
// 记录dfs遍历的所有路径
ArrayList<ArrayList<Integer>> result = new ArrayList<>();
// dfs遍历路径
dfs(root, new ArrayList<>(), result);
// 记录已经处理过的节点,理论上后续处理过的节点所在的路径无需再次处理
ArrayList<Integer> processNode = new ArrayList<>();
int father = target;
while (k > 0) {
judgeNode(finalRes, k--, result, processNode, father);
// 加入到已处理集合
processNode.add(father);
// 找到新的父节点
father = getFather(result, father);
}
return new ArrayList<>(finalRes);
}
private boolean alreadyChoose(ArrayList<Integer> processNodes, ArrayList<Integer> integers) {
for (Integer processNode : processNodes) {
if (integers.contains(processNode)) {
return true;
}
}
return false;
}
private void judgeNode(Set<Integer> finalRes, int k, ArrayList<ArrayList<Integer>> result,
ArrayList<Integer> processFather, int father) {
for (ArrayList<Integer> integers : result) {
if (alreadyChoose(processFather, integers)) {
continue;
}
// 根节点,仅需处理未处理过的孩子
if (father == -1) {
if (k < integers.size()) {
finalRes.add(integers.get(k));
}
} else {
// 非根节点,需处理包含father节点的路径
if (integers.contains(father)) {
int index = integers.indexOf(father);
if (index + k < integers.size()) {
finalRes.add(integers.get(index + k));
}
if (index - k >= 0) {
finalRes.add(integers.get(index - k));
}
}
}
}
}
/**
* 获取当前处理节点的父节点
* @param result
* @param target
* @return
*/
private int getFather(ArrayList<ArrayList<Integer>> result, int target) {
for (ArrayList<Integer> res : result) {
if (res.contains(target)) {
int index = res.indexOf(target);
if (index - 1 >= 0) {
return res.get(index - 1);
}
}
}
// 已经是树根了,无父节点
return -1;
}
private void dfs(TreeNode root, ArrayList<Integer> list, ArrayList<ArrayList<Integer>> result) {
list.add(root.val);
if (root.left == null && root.right == null) {
result.add(new ArrayList<>(list));
return;
}
if (root.left != null) {
dfs(root.left, list, result);
list.remove(list.size() - 1);
}
if (root.right != null) {
dfs(root.right, list, result);
list.remove(list.size() - 1);
}
}
}