思路一. 中序遍历,取第 K 个
思路二. 维护每个子树的大小
Java#
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
| import java.util.ArrayDeque;
import java.util.Deque;
class Solution {
public int kthSmallest(TreeNode root, int k) {
Deque<TreeNode> stack = new ArrayDeque<>();
TreeNode cur = root;
while (cur != null || !stack.isEmpty()) {
// 一路向左,把路径压栈
while (cur != null) {
stack.push(cur);
cur = cur.left;
}
// 弹出当前最左(当前未访问的最小)
cur = stack.pop();
k--;
if (k == 0) return cur.val;
// 转向右子树继续中序
cur = cur.right;
}
return 0;
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
| class Solution {
private int k;
private int ans;
public int kthSmallest(TreeNode root, int k) {
this.k = k;
inorder(root);
return ans;
}
private void inorder(TreeNode node) {
if (node == null) {
return;
}
inorder(node.left);
if (--k == 0) {
ans = node.val;
return;
}
inorder(node.right);
}
}
|
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
| import java.util.IdentityHashMap;
import java.util.Map;
class Solution2 {
private final Map<TreeNode, Integer> size = new IdentityHashMap<>();
public int kthSmallest(TreeNode root, int k) {
buildSize(root);
TreeNode cur = root;
while (cur != null) {
int leftSize = getSize(cur.left);
if (k <= leftSize) {
cur = cur.left;
} else if (k == leftSize + 1) {
return cur.val;
} else {
k -= (leftSize + 1);
cur = cur.right;
}
}
throw new IllegalArgumentException("k is out of range");
}
// 后序遍历:先算左右,再算自己
private int buildSize(TreeNode node) {
if (node == null) return 0;
int ls = buildSize(node.left);
int rs = buildSize(node.right);
int total = ls + rs + 1;
size.put(node, total);
return total;
}
private int getSize(TreeNode node) {
return node == null ? 0 : size.getOrDefault(node, 0);
}
}
|