Skip to content

Commit 28ba2dd

Browse files
committedFeb 4, 2023
feat: add solutions to lcof problem: No.54:
1 parent a0c9b80 commit 28ba2dd

File tree

7 files changed

+184
-206
lines changed

7 files changed

+184
-206
lines changed
 

‎lcof/面试题54. 二叉搜索树的第k大节点/README.md

+113-118
Original file line numberDiff line numberDiff line change
@@ -40,36 +40,13 @@
4040

4141
## 解法
4242

43-
朴素解法:
43+
**方法一:反序中序遍历**
4444

45-
1. 中序遍历,并使用数组存储遍历结果。
46-
2. 遍历结束,返回 `arr[arr.length - k]`
45+
由于二叉搜索树的中序遍历是升序的,因此可以反序中序遍历,即先递归遍历右子树,再访问根节点,最后递归遍历左子树。
4746

48-
_优化_
47+
这样就可以得到一个降序的序列,第 $k$ 个节点就是第 $k$ 大的节点。
4948

50-
其中,只关注**第 k 大节点的值**,可以选择倒序遍历,记录当前遍历节点的数量,当数量为 `k` 时,记录当前节点值做为返回值即可,而无需记录所有的遍历结果。
51-
52-
> 中序遍历的顺序是从小到大,倒序的中序遍历便是从大到小。
53-
54-
常规中序遍历:
55-
56-
```txt
57-
IN-ORDER(R)
58-
IN-ORDER(R.left)
59-
print(R.val)
60-
In-ORDER(R.right)
61-
```
62-
63-
倒序中序遍历:
64-
65-
```txt
66-
IN-ORDER-REVERSE(R)
67-
In-ORDER-REVERSE(R.right)
68-
print(R.val)
69-
IN-ORDER-REVERSE(R.left)
70-
```
71-
72-
若是抬杠说,可能每次 `k` 都是节点数量,那么倒序就毫无意义并且加长时间消耗。这些情况是无法假设的,如果 `k = 1`,那又该怎么说,选择倒序先得最大值,才是符合题意的精神。
49+
时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 是二叉搜索树的节点个数。
7350

7451
<!-- tabs:start -->
7552

@@ -86,19 +63,19 @@ IN-ORDER-REVERSE(R)
8663

8764
class Solution:
8865
def kthLargest(self, root: TreeNode, k: int) -> int:
89-
def inorder(root):
90-
if root is None:
91-
return
92-
inorder(root.right)
93-
self.cur -= 1
94-
if self.cur == 0:
95-
self.res = root.val
66+
def dfs(root):
67+
nonlocal k, ans
68+
if root is None or k == 0:
9669
return
97-
inorder(root.left)
98-
99-
self.cur = k
100-
inorder(root)
101-
return self.res
70+
dfs(root.right)
71+
k -= 1
72+
if k == 0:
73+
ans = root.val
74+
dfs(root.left)
75+
76+
ans = 0
77+
dfs(root)
78+
return ans
10279
```
10380

10481
### **Java**
@@ -114,66 +91,28 @@ class Solution:
11491
* }
11592
*/
11693
class Solution {
117-
private int cur;
118-
private int res;
94+
private int k;
95+
private int ans;
11996

12097
public int kthLargest(TreeNode root, int k) {
121-
cur = k;
122-
res = 0;
123-
inorder(root);
124-
return res;
98+
this.k = k;
99+
dfs(root);
100+
return ans;
125101
}
126102

127-
private void inorder(TreeNode root) {
128-
if (root == null) {
103+
private void dfs(TreeNode root) {
104+
if (root == null || k == 0) {
129105
return;
130106
}
131-
inorder(root.right);
132-
--cur;
133-
if (cur == 0) {
134-
res = root.val;
135-
return;
107+
dfs(root.right);
108+
if (--k == 0) {
109+
ans = root.val;
136110
}
137-
inorder(root.left);
111+
dfs(root.left);
138112
}
139113
}
140114
```
141115

142-
### **JavaScript**
143-
144-
```js
145-
/**
146-
* Definition for a binary tree node.
147-
* function TreeNode(val) {
148-
* this.val = val;
149-
* this.left = this.right = null;
150-
* }
151-
*/
152-
/**
153-
* @param {TreeNode} root
154-
* @param {number} k
155-
* @return {number}
156-
*/
157-
var kthLargest = function (root, k) {
158-
const inorder = root => {
159-
if (!root) {
160-
return;
161-
}
162-
inorder(root.right);
163-
--cur;
164-
if (cur == 0) {
165-
res = root.val;
166-
return;
167-
}
168-
inorder(root.left);
169-
};
170-
let res = 0;
171-
let cur = k;
172-
inorder(root);
173-
return res;
174-
};
175-
```
176-
177116
### **C++**
178117

179118
```cpp
@@ -189,31 +128,52 @@ var kthLargest = function (root, k) {
189128
class Solution {
190129
public:
191130
int kthLargest(TreeNode* root, int k) {
192-
cur = k;
193-
inorder(root);
194-
return res;
195-
}
196-
197-
private:
198-
int cur, res;
199-
200-
void inorder(TreeNode* root) {
201-
if (!root) {
202-
return;
203-
}
204-
inorder(root->right);
205-
--cur;
206-
if (cur == 0) {
207-
res = root->val;
208-
return;
209-
}
210-
inorder(root->left);
131+
int ans = 0;
132+
function<void(TreeNode*)> dfs = [&](TreeNode* root) {
133+
if (!root || !k) {
134+
return;
135+
}
136+
dfs(root->right);
137+
if (--k == 0) {
138+
ans = root->val;
139+
}
140+
dfs(root->left);
141+
};
142+
dfs(root);
143+
return ans;
211144
}
212145
};
213146
```
214147
215148
### **Go**
216149
150+
```go
151+
/**
152+
* Definition for a binary tree node.
153+
* type TreeNode struct {
154+
* Val int
155+
* Left *TreeNode
156+
* Right *TreeNode
157+
* }
158+
*/
159+
func kthLargest(root *TreeNode, k int) (ans int) {
160+
var dfs func(*TreeNode)
161+
dfs = func(root *TreeNode) {
162+
if root == nil || k == 0 {
163+
return
164+
}
165+
dfs(root.Right)
166+
k--
167+
if k == 0 {
168+
ans = root.Val
169+
}
170+
dfs(root.Left)
171+
}
172+
dfs(root)
173+
return
174+
}
175+
```
176+
217177
利用 Go 的特性,中序遍历“生产”的数字传到 `channel`,返回第 `k` 个。
218178

219179
```go
@@ -249,6 +209,38 @@ func inorder(ctx context.Context, cur *TreeNode, ch chan<- int) {
249209
}
250210
```
251211

212+
### **JavaScript**
213+
214+
```js
215+
/**
216+
* Definition for a binary tree node.
217+
* function TreeNode(val) {
218+
* this.val = val;
219+
* this.left = this.right = null;
220+
* }
221+
*/
222+
/**
223+
* @param {TreeNode} root
224+
* @param {number} k
225+
* @return {number}
226+
*/
227+
var kthLargest = function (root, k) {
228+
let ans = 0;
229+
const dfs = root => {
230+
if (!root || !k) {
231+
return;
232+
}
233+
dfs(root.right);
234+
if (--k == 0) {
235+
ans = root.val;
236+
}
237+
dfs(root.left);
238+
};
239+
dfs(root);
240+
return ans;
241+
};
242+
```
243+
252244
### **TypeScript**
253245

254246
```ts
@@ -338,21 +330,24 @@ impl Solution {
338330
* }
339331
*/
340332
public class Solution {
333+
private int ans;
334+
private int k;
335+
341336
public int KthLargest(TreeNode root, int k) {
342-
List<int> list = new List<int>();
343-
list = postorder(root, list);
344-
return list[list.Count() - k];
337+
this.k = k;
338+
dfs(root);
339+
return ans;
345340
}
346341

347-
public List<int> postorder(TreeNode root, List<int> list) {
348-
if (root == null) {
349-
return list;
350-
} else {
351-
postorder(root.left, list);
352-
list.Add(root.val);
353-
postorder(root.right, list);
342+
private void dfs(TreeNode root) {
343+
if (root == null || k == 0) {
344+
return;
354345
}
355-
return list;
346+
dfs(root.right);
347+
if (--k == 0) {
348+
ans = root.val;
349+
}
350+
dfs(root.left);
356351
}
357352
}
358353
```

‎lcof/面试题54. 二叉搜索树的第k大节点/Solution.cpp

+13-19
Original file line numberDiff line numberDiff line change
@@ -10,24 +10,18 @@
1010
class Solution {
1111
public:
1212
int kthLargest(TreeNode* root, int k) {
13-
cur = k;
14-
inorder(root);
15-
return res;
16-
}
17-
18-
private:
19-
int cur, res;
20-
21-
void inorder(TreeNode* root) {
22-
if (!root) {
23-
return;
24-
}
25-
inorder(root->right);
26-
--cur;
27-
if (cur == 0) {
28-
res = root->val;
29-
return;
30-
}
31-
inorder(root->left);
13+
int ans = 0;
14+
function<void(TreeNode*)> dfs = [&](TreeNode* root) {
15+
if (!root || !k) {
16+
return;
17+
}
18+
dfs(root->right);
19+
if (--k == 0) {
20+
ans = root->val;
21+
}
22+
dfs(root->left);
23+
};
24+
dfs(root);
25+
return ans;
3226
}
3327
};

‎lcof/面试题54. 二叉搜索树的第k大节点/Solution.cs

+14-13
Original file line numberDiff line numberDiff line change
@@ -8,22 +8,23 @@
88
* }
99
*/
1010
public class Solution {
11+
private int ans;
12+
private int k;
13+
1114
public int KthLargest(TreeNode root, int k) {
12-
List<int> list = new List<int>();
13-
list = postorder(root, list);
14-
return list[list.Count() - k];
15+
this.k = k;
16+
dfs(root);
17+
return ans;
1518
}
1619

17-
public List<int> postorder(TreeNode root, List<int> list) {
18-
if (root == null) {
19-
return list;
20-
} else {
21-
postorder(root.left, list);
22-
list.Add(root.val);
23-
postorder(root.right, list);
20+
private void dfs(TreeNode root) {
21+
if (root == null || k == 0) {
22+
return;
23+
}
24+
dfs(root.right);
25+
if (--k == 0) {
26+
ans = root.val;
2427
}
25-
return list;
28+
dfs(root.left);
2629
}
27-
28-
2930
}

0 commit comments

Comments
 (0)