forked from DengWangBao/Leetcode-Java
-
Notifications
You must be signed in to change notification settings - Fork 0
/
KthSmallestElementInBST.java
90 lines (79 loc) · 2.48 KB
/
KthSmallestElementInBST.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
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
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
import java.util.Stack;
/**
* 这题关键是follow up
* 如果更新频繁,则通常的做法每次都是O(n),更优的做法是O(lgn)
* 即给node中记录左子树的节点个数,这样在找kth smallest时流程如下:
* 假设root的左子树节点有N个,则
* 1, 当K=N+1时,kth就是root
* 2, 当K<N+1时,kth就到左子树中找
* 3, 当K>N+1时,就到右子树中找第K-N-1个
* 所以当给定一棵树时,我们要先重建一下这棵树,统计一下各节点的左子树节点数,虽然首次是O(n)
* 但是之后就是O(h)了。
*/
public class KthSmallestElementInBST {
public int kthSmallest(TreeNode root, int k) {
int[] kth = new int[1];
inorderTraversal(root, k, kth);
return kth[0];
}
private int inorderTraversal(TreeNode root, int k, int[] kth) {
if (root == null) {
return k;
}
k = inorderTraversal(root.left, k, kth);
if (--k == 0) {
kth[0] = root.val;
return 0;
}
return inorderTraversal(root.right, k, kth);
}
/**
* 非递归法
*/
public int kthSmallest2(TreeNode root, int k) {
Stack<TreeNode> stack = new Stack<>();
while (root != null || !stack.isEmpty()) {
if (root != null) {
stack.push(root);
root = root.left;
} else {
root = stack.pop();
if (--k == 0) {
return root.val;
}
root = root.right;
}
}
throw new IllegalStateException();
}
/**
* Morris
*/
private int kthSmallest3(TreeNode root, int k) {
TreeNode temp;
while (root != null) {
if (root.left == null) {
if (--k == 0) {
return root.val;
}
root = root.right;
} else {
temp = root.left;
while (temp.right != null && temp.right != root) {
temp = temp.right;
}
if (temp.right == null) {
temp.right = root;
root = root.left;
} else {
temp.right = null;
if (--k == 0) {
return root.val;
}
root = root.right;
}
}
}
throw new IllegalStateException();
}
}