Skip to content

Commit 0eb2379

Browse files
author
oushihao
committed
feat(two-sum-iv-input-is-a-bst): 递归遍历 + 哈希表 | 双指针
1 parent 5fdd238 commit 0eb2379

File tree

8 files changed

+293
-1
lines changed

8 files changed

+293
-1
lines changed

.vscode/settings.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
{
2-
"commentTranslate.hover.enabled": true
2+
"commentTranslate.hover.enabled": true,
3+
"cSpell.words": ["inorder"]
34
}

assets/data/category.json

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,12 @@
116116
"path": "../../problemset/minimum-index-sum-of-two-lists/README.md",
117117
"difficulty": "简单"
118118
},
119+
{
120+
"id": 653,
121+
"title": "两数之和 IV - 输入 BST",
122+
"path": "../../problemset/two-sum-iv-input-is-a-bst/README.md",
123+
"difficulty": "简单"
124+
},
119125
{
120126
"id": 720,
121127
"title": "词典中最长的单词",
@@ -954,6 +960,12 @@
954960
"path": "../../problemset/happy-number/README.md",
955961
"difficulty": "简单"
956962
},
963+
{
964+
"id": 653,
965+
"title": "两数之和 IV - 输入 BST",
966+
"path": "../../problemset/two-sum-iv-input-is-a-bst/README.md",
967+
"difficulty": "简单"
968+
},
957969
{
958970
"id": 917,
959971
"title": "仅仅反转字母",
@@ -1634,6 +1646,12 @@
16341646
"path": "../../problemset/construct-string-from-binary-tree/README.md",
16351647
"difficulty": "简单"
16361648
},
1649+
{
1650+
"id": 653,
1651+
"title": "两数之和 IV - 输入 BST",
1652+
"path": "../../problemset/two-sum-iv-input-is-a-bst/README.md",
1653+
"difficulty": "简单"
1654+
},
16371655
{
16381656
"id": 838,
16391657
"title": "推多米诺",
@@ -1934,6 +1952,12 @@
19341952
"title": "根据二叉树创建字符串",
19351953
"path": "../../problemset/construct-string-from-binary-tree/README.md",
19361954
"difficulty": "简单"
1955+
},
1956+
{
1957+
"id": 653,
1958+
"title": "两数之和 IV - 输入 BST",
1959+
"path": "../../problemset/two-sum-iv-input-is-a-bst/README.md",
1960+
"difficulty": "简单"
19371961
}
19381962
]
19391963
},

assets/data/problems.json

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1919,6 +1919,16 @@
19191919
"url": "https://leetcode-cn.com/problems/construct-string-from-binary-tree/",
19201920
"path": "../../problemset/construct-string-from-binary-tree/README.md"
19211921
},
1922+
{
1923+
"id": 653,
1924+
"title": {
1925+
"cn": "两数之和 IV - 输入 BST",
1926+
"en": "two-sum-iv-input-is-a-bst"
1927+
},
1928+
"difficulty": "简单",
1929+
"url": "https://leetcode-cn.com/problems/two-sum-iv-input-is-a-bst/",
1930+
"path": "../../problemset/two-sum-iv-input-is-a-bst/README.md"
1931+
},
19221932
{
19231933
"id": 688,
19241934
"title": {

assets/docs/CATEGORY.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
| 202. [快乐数](../../problemset/happy-number/README.md) | 简单 |
2424
| 432. [全 O(1) 的数据结构](../../problemset/all-oone-data-structure/README.md) | 困难 |
2525
| 599. [两个列表的最小索引总和](../../problemset/minimum-index-sum-of-two-lists/README.md) | 简单 |
26+
| 653. [两数之和 IV - 输入 BST](../../problemset/two-sum-iv-input-is-a-bst/README.md) | 简单 |
2627
| 720. [词典中最长的单词](../../problemset/longest-word-in-dictionary/README.md) | 简单 |
2728
| 884. [两句话中的不常见单词](../../problemset/uncommon-words-from-two-sentences/README.md) | 简单 |
2829
| 1001. [网格照明](../../problemset/grid-illumination/README.md) | 困难 |
@@ -196,6 +197,7 @@
196197
| 165. [比较版本号](../../problemset/compare-version-numbers/README.md) | 中等 |
197198
| 167. [两数之和 II - 输入有序数组](../../problemset/two-sum-ii-input-array-is-sorted/README.md) | 中等 |
198199
| 202. [快乐数](../../problemset/happy-number/README.md) | 简单 |
200+
| 653. [两数之和 IV - 输入 BST](../../problemset/two-sum-iv-input-is-a-bst/README.md) | 简单 |
199201
| 917. [仅仅反转字母](../../problemset/reverse-only-letters/README.md) | 简单 |
200202

201203
## 模拟
@@ -326,6 +328,7 @@
326328
| 589. [N 叉树的前序遍历](../../problemset/n-ary-tree-preorder-traversal/README.md) | 简单 |
327329
| 590. [N 叉树的后序遍历](../../problemset/n-ary-tree-postorder-traversal/README.md) | 简单 |
328330
| 606. [根据二叉树创建字符串](../../problemset/construct-string-from-binary-tree/README.md) | 简单 |
331+
| 653. [两数之和 IV - 输入 BST](../../problemset/two-sum-iv-input-is-a-bst/README.md) | 简单 |
329332
| 838. [推多米诺](../../problemset/push-dominoes/README.md) | 中等 |
330333
| 1020. [飞地的数量](../../problemset/number-of-enclaves/README.md) | 中等 |
331334
| 1765. [地图中的最高点](../../problemset/map-of-highest-peak/README.md) | 中等 |
@@ -397,6 +400,7 @@
397400
| 199. [二叉树的右视图](../../problemset/binary-tree-right-side-view/README.md) | 中等 |
398401
| 589. [N 叉树的前序遍历](../../problemset/n-ary-tree-preorder-traversal/README.md) | 简单 |
399402
| 606. [根据二叉树创建字符串](../../problemset/construct-string-from-binary-tree/README.md) | 简单 |
403+
| 653. [两数之和 IV - 输入 BST](../../problemset/two-sum-iv-input-is-a-bst/README.md) | 简单 |
400404

401405
## 枚举
402406

assets/docs/PROBLEMS.md

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

385385
[606. 根据二叉树创建字符串](../../problemset/construct-string-from-binary-tree/README.md)
386386

387+
[653. 两数之和 IV - 输入 BST](../../problemset/two-sum-iv-input-is-a-bst/README.md)
388+
387389
[688. 骑士在棋盘上的概率](../../problemset/knight-probability-in-chessboard/README.md)
388390

389391
[720. 词典中最长的单词](../../problemset/longest-word-in-dictionary/README.md)
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
# 两数之和 IV - 输入 BST
2+
3+
> 难度:简单
4+
>
5+
> https://leetcode-cn.com/problems/two-sum-iv-input-is-a-bst/
6+
7+
## 题目
8+
9+
给定一个二叉搜索树 `root` 和一个目标结果 `k`,如果 `BST` 中存在两个元素且它们的
10+
和等于给定的目标结果,则返回 `true`
11+
12+
### 示例
13+
14+
#### 示例 1:
15+
16+
![two-sum-iv-input-is-a-bst-1](https://user-images.githubusercontent.com/54696834/159190975-736a58d3-a89a-4119-bfb6-cea13459f94b.jpg)
17+
18+
```
19+
输入: root = [5,3,6,2,4,null,7], k = 9
20+
输出: true
21+
```
22+
23+
#### 示例 2:
24+
25+
![two-sum-iv-input-is-a-bst-2](https://user-images.githubusercontent.com/54696834/159190978-0f9da24e-bc9a-47ed-b916-63124d498a11.jpg)
26+
27+
```
28+
输入: root = [5,3,6,2,4,null,7], k = 28
29+
输出: false
30+
```
31+
32+
## 解题
33+
34+
### 广度优先搜索 + 哈希表
35+
36+
```typescript
37+
/**
38+
* 广度优先搜索 + 哈希表
39+
* @desc 时间复杂度 O(N) 空间复杂度 O(N)
40+
* @param root
41+
* @param k
42+
* @returns
43+
*/
44+
export function findTarget(root: TreeNode | null, k: number): boolean {
45+
if (root === null) return false;
46+
47+
const set = new Set<number>();
48+
const stack = [root];
49+
50+
while (stack.length > 0) {
51+
const node = stack.pop()!;
52+
53+
const diff = k - node.val;
54+
if (set.has(diff)) return true;
55+
set.add(node.val);
56+
57+
node.left && stack.push(node.left);
58+
node.right && stack.push(node.right);
59+
}
60+
61+
return false;
62+
}
63+
```
64+
65+
### 深度优先搜索 + 哈希表
66+
67+
```typescript
68+
/**
69+
* 深度优先搜索 + 哈希表
70+
* @desc 时间复杂度 O(N) 空间复杂度 O(N)
71+
* @param root
72+
* @param k
73+
* @returns
74+
*/
75+
export function findTarget2(root: TreeNode | null, k: number): boolean {
76+
if (root === null) return false;
77+
return dfs(root, k);
78+
79+
function dfs(node: TreeNode, k: number, set = new Set<number>()): boolean {
80+
if (set.has(k - node.val)) return true;
81+
82+
set.add(node.val);
83+
84+
if (
85+
(node.left && dfs(node.left, k, set)) ||
86+
(node.right && dfs(node.right, k, set))
87+
) {
88+
return true;
89+
}
90+
91+
return false;
92+
}
93+
}
94+
```
95+
96+
### 深度优先搜索 + 中序遍历 + 双指针
97+
98+
```typescript
99+
/**
100+
* 深度优先搜索 + 中序遍历 + 双指针
101+
* @desc 时间复杂度 O(N) 空间复杂度 O(N)
102+
* @param root
103+
* @param k
104+
* @returns
105+
*/
106+
export function findTarget3(root: TreeNode | null, k: number): boolean {
107+
if (root === null) return false;
108+
109+
const list: number[] = [];
110+
inorderTraversal(root, list);
111+
112+
let left = 0;
113+
let right = list.length - 1;
114+
115+
while (left < right) {
116+
const sum = list[left] + list[right];
117+
if (sum === k) return true;
118+
if (sum < k) left++;
119+
else right--;
120+
}
121+
122+
return false;
123+
124+
function inorderTraversal(node: TreeNode | null, list: number[]) {
125+
if (!node) return;
126+
inorderTraversal(node.left, list);
127+
list.push(node.val);
128+
inorderTraversal(node.right, list);
129+
}
130+
}
131+
```
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import { TreeNode, createTreeNode } from '~/utils/treeNode';
2+
import { findTarget, findTarget2, findTarget3 } from '.';
3+
4+
describe('两数之和 IV - 输入 BST', () => {
5+
describe('广度优先搜索 + 哈希表', () => {
6+
testCase(findTarget);
7+
});
8+
9+
describe('广度优先搜索 + 哈希表', () => {
10+
testCase(findTarget2);
11+
});
12+
13+
describe('广度优先搜索 + 哈希表', () => {
14+
testCase(findTarget3);
15+
});
16+
});
17+
18+
function testCase(fn: (root: TreeNode | null, k: number) => boolean) {
19+
it('示例一', () => {
20+
const root = createTreeNode([5, 3, 6, 2, 4, null, 7]);
21+
const k = 9;
22+
const expected = true;
23+
expect(fn(root, k)).toBe(expected);
24+
});
25+
26+
it('示例二', () => {
27+
const root = createTreeNode([5, 3, 6, 2, 4, null, 7]);
28+
const k = 28;
29+
const expected = false;
30+
expect(fn(root, k)).toBe(expected);
31+
});
32+
}
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
import { TreeNode } from '~/utils/treeNode';
2+
3+
/**
4+
* 广度优先搜索 + 哈希表
5+
* @desc 时间复杂度 O(N) 空间复杂度 O(N)
6+
* @param root
7+
* @param k
8+
* @returns
9+
*/
10+
export function findTarget(root: TreeNode | null, k: number): boolean {
11+
if (root === null) return false;
12+
13+
const set = new Set<number>();
14+
const stack = [root];
15+
16+
while (stack.length > 0) {
17+
const node = stack.pop()!;
18+
19+
const diff = k - node.val;
20+
if (set.has(diff)) return true;
21+
set.add(node.val);
22+
23+
node.left && stack.push(node.left);
24+
node.right && stack.push(node.right);
25+
}
26+
27+
return false;
28+
}
29+
30+
/**
31+
* 深度优先搜索 + 哈希表
32+
* @desc 时间复杂度 O(N) 空间复杂度 O(N)
33+
* @param root
34+
* @param k
35+
* @returns
36+
*/
37+
export function findTarget2(root: TreeNode | null, k: number): boolean {
38+
if (root === null) return false;
39+
return dfs(root, k);
40+
41+
function dfs(node: TreeNode, k: number, set = new Set<number>()): boolean {
42+
if (set.has(k - node.val)) return true;
43+
44+
set.add(node.val);
45+
46+
if (
47+
(node.left && dfs(node.left, k, set)) ||
48+
(node.right && dfs(node.right, k, set))
49+
) {
50+
return true;
51+
}
52+
53+
return false;
54+
}
55+
}
56+
57+
/**
58+
* 深度优先搜索 + 中序遍历 + 双指针
59+
* @desc 时间复杂度 O(N) 空间复杂度 O(N)
60+
* @param root
61+
* @param k
62+
* @returns
63+
*/
64+
export function findTarget3(root: TreeNode | null, k: number): boolean {
65+
if (root === null) return false;
66+
67+
const list: number[] = [];
68+
inorderTraversal(root, list);
69+
70+
let left = 0;
71+
let right = list.length - 1;
72+
73+
while (left < right) {
74+
const sum = list[left] + list[right];
75+
if (sum === k) return true;
76+
if (sum < k) left++;
77+
else right--;
78+
}
79+
80+
return false;
81+
82+
function inorderTraversal(node: TreeNode | null, list: number[]) {
83+
if (!node) return;
84+
inorderTraversal(node.left, list);
85+
list.push(node.val);
86+
inorderTraversal(node.right, list);
87+
}
88+
}

0 commit comments

Comments
 (0)