Skip to content

Commit ba31a60

Browse files
committed
feat: leetcode 669
1 parent 4eb7673 commit ba31a60

File tree

8 files changed

+203
-1
lines changed

8 files changed

+203
-1
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
<p align="center">
44
<!-- TOPICS COUNT START -->
5-
<img src="https://img.shields.io/badge/-进度:489-green" alt="进度:489">
5+
<img src="https://img.shields.io/badge/-进度:490-green" alt="进度:490">
66
<!-- TOPICS COUNT END -->
77
<a href="./assets/docs/TOPICS.md"><img src="https://img.shields.io/badge/-题库目录-blue" alt="题库目录"></a>
88
<a href="./assets/docs/CATEGORIES.md"><img src="https://img.shields.io/badge/-题库分类-red" alt="题库分类"></a>

assets/data/categories.json

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3236,6 +3236,12 @@
32363236
"path": "./problemset/maximum-width-of-binary-tree/README.md",
32373237
"difficulty": "中等"
32383238
},
3239+
{
3240+
"id": "669",
3241+
"title": "修剪二叉搜索树",
3242+
"path": "./problemset/trim-a-binary-search-tree/README.md",
3243+
"difficulty": "中等"
3244+
},
32393245
{
32403246
"id": "675",
32413247
"title": "为高尔夫比赛砍树",
@@ -3825,6 +3831,12 @@
38253831
"path": "./problemset/maximum-width-of-binary-tree/README.md",
38263832
"difficulty": "中等"
38273833
},
3834+
{
3835+
"id": "669",
3836+
"title": "修剪二叉搜索树",
3837+
"path": "./problemset/trim-a-binary-search-tree/README.md",
3838+
"difficulty": "中等"
3839+
},
38283840
{
38293841
"id": "687",
38303842
"title": "最长同值路径",

assets/data/topics.json

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3399,6 +3399,16 @@
33993399
"url": "https://leetcode.cn/problems/kth-smallest-number-in-multiplication-table/",
34003400
"path": "./problemset/kth-smallest-number-in-multiplication-table/README.md"
34013401
},
3402+
{
3403+
"id": "669",
3404+
"title": {
3405+
"cn": "修剪二叉搜索树",
3406+
"en": "trim-a-binary-search-tree"
3407+
},
3408+
"difficulty": "中等",
3409+
"url": "https://leetcode.cn/problems/trim-a-binary-search-tree/",
3410+
"path": "./problemset/trim-a-binary-search-tree/README.md"
3411+
},
34023412
{
34033413
"id": "675",
34043414
"title": {

assets/docs/CATEGORIES.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -593,6 +593,7 @@
593593
| 654. [最大二叉树](../../problemset/maximum-binary-tree/README.md) | 中等 |
594594
| 655. [输出二叉树](../../problemset/print-binary-tree/README.md) | 中等 |
595595
| 662. [二叉树最大宽度](../../problemset/maximum-width-of-binary-tree/README.md) | 中等 |
596+
| 669. [修剪二叉搜索树](../../problemset/trim-a-binary-search-tree/README.md) | 中等 |
596597
| 675. [为高尔夫比赛砍树](../../problemset/cut-off-trees-for-golf-event/README.md) | 困难 |
597598
| 687. [最长同值路径](../../problemset/longest-univalue-path/README.md) | 中等 |
598599
| 691. [贴纸拼词](../../problemset/stickers-to-spell-word/README.md) | 困难 |
@@ -712,6 +713,7 @@
712713
| 654. [最大二叉树](../../problemset/maximum-binary-tree/README.md) | 中等 |
713714
| 655. [输出二叉树](../../problemset/print-binary-tree/README.md) | 中等 |
714715
| 662. [二叉树最大宽度](../../problemset/maximum-width-of-binary-tree/README.md) | 中等 |
716+
| 669. [修剪二叉搜索树](../../problemset/trim-a-binary-search-tree/README.md) | 中等 |
715717
| 687. [最长同值路径](../../problemset/longest-univalue-path/README.md) | 中等 |
716718
| 814. [二叉树剪枝](../../problemset/binary-tree-pruning/README.md) | 中等 |
717719
| 919. [完全二叉树插入器](../../problemset/complete-binary-tree-inserter/README.md) | 中等 |

assets/docs/TOPICS.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -680,6 +680,8 @@
680680

681681
[668. 乘法表中第k小的数](../../problemset/kth-smallest-number-in-multiplication-table/README.md)
682682

683+
[669. 修剪二叉搜索树](../../problemset/trim-a-binary-search-tree/README.md)
684+
683685
[675. 为高尔夫比赛砍树](../../problemset/cut-off-trees-for-golf-event/README.md)
684686

685687
[676. 实现一个魔法字典](../../problemset/implement-magic-dictionary/README.md)
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
# 修剪二叉搜索树
2+
3+
> 难度:中等
4+
>
5+
> https://leetcode.cn/problems/trim-a-binary-search-tree/
6+
7+
## 题目
8+
9+
给你二叉搜索树的根节点 `root` ,同时给定最小边界 `low` 和最大边界 `high`。通过修剪二叉搜索树,使得所有节点的值在`[low, high]`中。修剪树 **不应该** 改变保留在树中的元素的相对结构 (即,如果没有被移除,原有的父代子代关系都应当保留)。 可以证明,存在 **唯一的答案** 。
10+
11+
所以结果应当返回修剪好的二叉搜索树的新的根节点。注意,根节点可能会根据给定的边界发生改变。
12+
13+
### 示例
14+
15+
#### 示例 1:
16+
17+
![image](https://user-images.githubusercontent.com/54696834/189466720-dfdd5148-0e82-4d1c-a308-9859e604f863.png)
18+
19+
```
20+
输入:root = [1,0,2], low = 1, high = 2
21+
输出:[1,null,2]
22+
```
23+
24+
#### 示例 2:
25+
26+
![image](https://user-images.githubusercontent.com/54696834/189466724-aa1cca80-66e4-4711-84eb-f708eb7d3cd3.png)
27+
28+
```
29+
输入:root = [3,0,4,null,2,null,null,1], low = 1, high = 3
30+
输出:[3,2,null,1]
31+
```
32+
33+
## 解题
34+
35+
### 递归
36+
37+
```ts
38+
/**
39+
* 递归
40+
* @desc 时间复杂度 O(N) 空间复杂度 O(N)
41+
* @param root
42+
* @param low
43+
* @param high
44+
* @returns
45+
*/
46+
export function trimBST(root: TreeNode | null, low: number, high: number): TreeNode | null {
47+
if (!root) return null
48+
49+
if (root.val < low) {
50+
return trimBST(root.right, low, high)
51+
}
52+
else if (root.val > high) {
53+
return trimBST(root.left, low, high)
54+
}
55+
else {
56+
root.left = trimBST(root.left, low, high)
57+
root.right = trimBST(root.right, low, high)
58+
return root
59+
}
60+
}
61+
```
62+
63+
### 迭代
64+
65+
```ts
66+
/**
67+
* 迭代
68+
* @desc 时间复杂度 O(N) 空间复杂度 O(N)
69+
* @param root
70+
* @param low
71+
* @param high
72+
* @returns
73+
*/
74+
export function trimBST2(root: TreeNode | null, low: number, high: number): TreeNode | null {
75+
while (root && (root.val < low || root.val > high)) {
76+
if (root.val < low) root = root.right
77+
else root = root.left
78+
}
79+
if (!root) return null
80+
81+
for (let node = root; node.left;) {
82+
if (node.left.val < low)
83+
node.left = node.left.right
84+
85+
else
86+
node = node.left
87+
}
88+
for (let node = root; node.right;) {
89+
if (node.right.val > high)
90+
node.right = node.right.left
91+
92+
else
93+
node = node.right
94+
}
95+
return root
96+
}
97+
```
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { describe, expect, it } from 'vitest'
2+
import { trimBST, trimBST2 } from '.'
3+
import type { TreeNode } from '~/utils/treeNode'
4+
import { createTreeNode } from '~/utils/treeNode'
5+
6+
describe('修剪二叉搜索树', () => {
7+
describe('递归', () => testCase(trimBST))
8+
describe('迭代', () => testCase(trimBST2))
9+
})
10+
11+
function testCase(fn: (root: TreeNode | null, low: number, high: number) => TreeNode | null) {
12+
it.each([
13+
[
14+
[1, 0, 2], 1, 2, [1, null, 2],
15+
],
16+
[
17+
[3, 0, 4, null, 2, null, null, 1], 1, 3, [3, 2, null, 1],
18+
],
19+
])('示例%#', (root, low, high, expected) => {
20+
expect(fn(createTreeNode(root), low, high)).toStrictEqual(createTreeNode(expected))
21+
})
22+
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import type { TreeNode } from '~/utils/treeNode'
2+
3+
/**
4+
* 递归
5+
* @desc 时间复杂度 O(N) 空间复杂度 O(N)
6+
* @param root
7+
* @param low
8+
* @param high
9+
* @returns
10+
*/
11+
export function trimBST(root: TreeNode | null, low: number, high: number): TreeNode | null {
12+
if (!root) return null
13+
14+
if (root.val < low) {
15+
return trimBST(root.right, low, high)
16+
}
17+
else if (root.val > high) {
18+
return trimBST(root.left, low, high)
19+
}
20+
else {
21+
root.left = trimBST(root.left, low, high)
22+
root.right = trimBST(root.right, low, high)
23+
return root
24+
}
25+
}
26+
27+
/**
28+
* 迭代
29+
* @desc 时间复杂度 O(N) 空间复杂度 O(N)
30+
* @param root
31+
* @param low
32+
* @param high
33+
* @returns
34+
*/
35+
export function trimBST2(root: TreeNode | null, low: number, high: number): TreeNode | null {
36+
while (root && (root.val < low || root.val > high)) {
37+
if (root.val < low) root = root.right
38+
else root = root.left
39+
}
40+
if (!root) return null
41+
42+
for (let node = root; node.left;) {
43+
if (node.left.val < low)
44+
node.left = node.left.right
45+
46+
else
47+
node = node.left
48+
}
49+
for (let node = root; node.right;) {
50+
if (node.right.val > high)
51+
node.right = node.right.left
52+
53+
else
54+
node = node.right
55+
}
56+
return root
57+
}

0 commit comments

Comments
 (0)