LC.P863[二叉树中所有距离为 K 的结点]

思路

是一类特殊的,对二叉树中相邻的节点建图,边的权重为1。接着从目标节点出发遍历图,找到距离为k的节点。

方法一:建图+BFS

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
int N = 510, M = 4 * N, idx = 0;
int[] he = new int[N], e = new int[M], ne = new int[M];
boolean[] visited = new boolean[N];

private void add(int a, int b) {
e[idx] = b;
ne[idx] = he[a];
he[a] = idx++;
}

public List<Integer> distanceK(TreeNode root, TreeNode target, int k) {
Arrays.fill(he, -1);
dfs(root);
List<Integer> ans = new ArrayList<>();
Deque<Integer> queue = new ArrayDeque<>();
queue.offer(target.val);
visited[target.val] = true;
while (!queue.isEmpty() && k >= 0) {
int size = queue.size();
while (size-- > 0) {
int cur = queue.poll();
if (k == 0) {
ans.add(cur);
continue;
}
for (int i = he[cur]; i != -1; i = ne[i]) {
int j = e[i];
if (!visited[j]) {
queue.offer(j);
visited[j] = true;
}
}
}
--k;
}
return ans;
}

private void dfs(TreeNode node) {
if (node == null) return;
if (node.left != null) {
add(node.val, node.left.val);
add(node.left.val, node.val);
dfs(node.left);
}
if (node.right != null) {
add(node.val, node.right.val);
add(node.right.val, node.val);
dfs(node.right);
}
}
}
  • 时间复杂度:$O(n)$
  • 空间复杂度:$O(n)$

方法二:建图+迭代

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
int N = 510, M = 4 * N, idx = 0;
int[] he = new int[N], e = new int[M], ne = new int[M];
boolean[] visited = new boolean[N];
List<Integer> ans;

private void add(int a, int b) {
e[idx] = b;
ne[idx] = he[a];
he[a] = idx++;
}

public List<Integer> distanceK(TreeNode root, TreeNode target, int k) {
ans = new ArrayList<>();
Arrays.fill(he, -1);
dfs(root);
visited[target.val] = true;
find(target.val, k, 0);
return ans;
}

private void find(int node, int k, int cur) {
if (cur == k) {
ans.add(node);
return;
}
for (int i = he[node]; i != -1; i = ne[i]) {
int j = e[i];
if (!visited[j]) {
visited[j] = true;
find(j, k, cur + 1);
}
}
}

private void dfs(TreeNode node) {
if (node == null) return;
if (node.left != null) {
add(node.val, node.left.val);
add(node.left.val, node.val);
dfs(node.left);
}
if (node.right != null) {
add(node.val, node.right.val);
add(node.right.val, node.val);
dfs(node.right);
}
}
}
  • 时间复杂度:$O(n)$
  • 空间复杂度:$O(n)$

方法三:建图(map)+迭代

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
Map<Integer, List<Integer>> adj = new HashMap<>();
boolean[] visited = new boolean[510];
List<Integer> ans = new ArrayList<>();

private void add(int a, int b) {
adj.computeIfAbsent(a, key -> new ArrayList<>()).add(b);
}

public List<Integer> distanceK(TreeNode root, TreeNode target, int k) {
dfs(root);
visited[target.val] = true;
find(target.val, k, 0);
return ans;
}

private void find(int node, int k, int cur) {
if (cur == k) {
ans.add(node);
return;
}
List<Integer> list = adj.get(node);
if (list == null) return;
for (Integer i : list) {
if (!visited[i]) {
visited[i] = true;
find(i, k, cur + 1);
}
}
}

private void dfs(TreeNode node) {
if (node == null) return;
if (node.left != null) {
add(node.val, node.left.val);
add(node.left.val, node.val);
dfs(node.left);
}
if (node.right != null) {
add(node.val, node.right.val);
add(node.right.val, node.val);
dfs(node.right);
}
}
}
  • 时间复杂度:$O(n)$
  • 空间复杂度:$O(n)$