Skip to content

Commit 5389e91

Browse files
Merge pull request SharingSource#513 from SharingSource/ac_oier
✨style: Bulk processing format
2 parents 7c73f44 + c0bcc28 commit 5389e91

6 files changed

+120
-20
lines changed

Index/二叉树.md

+1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
| [240. 搜索二维矩阵 II](https://leetcode-cn.com/problems/search-a-2d-matrix-ii/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/search-a-2d-matrix-ii/solution/gong-shui-san-xie-yi-ti-shuang-jie-er-fe-y1ns/) | 中等 | 🤩🤩🤩🤩 |
55
| [297. 二叉树的序列化与反序列化](https://leetcode-cn.com/problems/serialize-and-deserialize-binary-tree/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/xu-lie-hua-er-cha-shu-lcof/solution/gong-shui-san-xie-er-cha-shu-de-xu-lie-h-n89a/) | 困难 | 🤩🤩🤩🤩🤩 |
66
| [437. 路径总和 III](https://leetcode-cn.com/problems/path-sum-iii/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/path-sum-iii/solution/gong-shui-san-xie-yi-ti-shuang-jie-dfs-q-usa7/) | 中等 | 🤩🤩🤩🤩 |
7+
| [449. 序列化和反序列化二叉搜索树](https://leetcode.cn/problems/serialize-and-deserialize-bst/) | [LeetCode 题解链接](https://leetcode.cn/problems/serialize-and-deserialize-bst/solution/by-ac_oier-ncwn/) | 中等 | 🤩🤩🤩🤩 |
78
| [563. 二叉树的坡度](https://leetcode-cn.com/problems/binary-tree-tilt/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/binary-tree-tilt/solution/gong-shui-san-xie-jian-dan-er-cha-shu-di-ekz4/) | 简单 | 🤩🤩🤩🤩 |
89
| [606. 根据二叉树创建字符串](https://leetcode-cn.com/problems/construct-string-from-binary-tree/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/construct-string-from-binary-tree/solution/by-ac_oier-i2sk/) | 简单 | 🤩🤩🤩🤩 |
910
| [653. 两数之和 IV - 输入 BST](https://leetcode-cn.com/problems/two-sum-iv-input-is-a-bst/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/two-sum-iv-input-is-a-bst/solution/by-ac_oier-zr4o/) | 简单 | 🤩🤩🤩🤩 |

LeetCode/1721-1730/1728. 猫和老鼠 II(困难).md

+3-3
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ Tag : 「博弈论」、「动态规划」、「记忆化搜索」
8282

8383
当时在 [(题解) 913. 猫和老鼠](https://leetcode.cn/problems/cat-and-mouse/solution/gong-shui-san-xie-dong-tai-gui-hua-yun-y-0bx1/) 没能证出来更小 $K$ 值(回合数)的正确性,用的 $2n^2$ 做的 ,其余题解说 $2 n$ 合法,后来也被证实是错误的。
8484

85-
对于本题如果用相同的分析思路,状态数多达 $8 * 8 * 8 * 8 * 2 = 8192$ 种,题目很贴心调整了规则为 $1000$ 步以内为猫获胜,但证明 $K$ 的理论上界仍是困难(上次分析不出来,这次压根不想分析
85+
对于本题如果用相同的分析思路,状态数多达 $8 \times 8 \times 8 \times 8 \times 2 = 8192$ 种,题目很贴心调整了规则为 $1000$ 步以内为猫获胜,但证明 $K$ 的理论上界仍是困难(上次分析不出来,这次压根不想分析
8686

8787
如果忽略 $K$ 值分析,代码还是很好写的:定义函数 `int dfs(int x, int y, int p, int q, int k)` 并配合记忆化搜索,其中鼠位于 $(x, y)$,猫位于 $(p, q)$,当前轮数为 $k$(由 $k$ 的奇偶性可知是谁的回合)。
8888

@@ -151,8 +151,8 @@ class Solution {
151151
}
152152
}
153153
```
154-
* 时间复杂度:令 $n$ 和 $m$ 分别为矩阵的长宽,最长移动距离为 $L$,复杂度为 $O(n^2 * m^2 * 1000 * 4 * L)$
155-
* 空间复杂度:$O(n^2 * m^2 * 1000)$
154+
* 时间复杂度:令 $n$ 和 $m$ 分别为矩阵的长宽,最长移动距离为 $L$,复杂度为 $O(n^2 \times m^2 \times 1000 \times 4 \times L)$
155+
* 空间复杂度:$O(n^2 \times m^2 \times 1000)$
156156

157157
---
158158

LeetCode/1751-1760/1751. 最多可以参加的会议数目 II(困难).md

+4-4
Original file line numberDiff line numberDiff line change
@@ -105,8 +105,8 @@ class Solution {
105105
}
106106
}
107107
```
108-
* 时间复杂度:排序复杂度为 $O(n\log{n})$,循环 `n` 个事件,每次循环需要往回找一个事件,复杂度为 $O(n)$,并更新 `k` 个状态,复杂度为 $O(k)$,因此转移的复杂度为 $O(n * (n + k))$;总的复杂度为 $O(n * (n + k + \log{n}))$
109-
* 空间复杂度:$O(n * k)$
108+
* 时间复杂度:排序复杂度为 $O(n\log{n})$,循环 `n` 个事件,每次循环需要往回找一个事件,复杂度为 $O(n)$,并更新 `k` 个状态,复杂度为 $O(k)$,因此转移的复杂度为 $O(n \times (n + k))$;总的复杂度为 $O(n \times (n + k + \log{n}))$
109+
* 空间复杂度:$O(n \times k)$
110110

111111
---
112112

@@ -145,8 +145,8 @@ class Solution {
145145
}
146146
}
147147
```
148-
* 时间复杂度:排序复杂度为 $O(n\log{n})$,循环 `n` 个事件,每次循环需要往回找一个事件,复杂度为 $O(\log{n})$,并更新 `k` 个状态,复杂度为 $O(k)$,因此转移的复杂度为 $O(n * (\log{n} + k))$;总的复杂度为 $O(n * (k + \log{n}))$
149-
* 空间复杂度:$O(n * k)$
148+
* 时间复杂度:排序复杂度为 $O(n\log{n})$,循环 `n` 个事件,每次循环需要往回找一个事件,复杂度为 $O(\log{n})$,并更新 `k` 个状态,复杂度为 $O(k)$,因此转移的复杂度为 $O(n \times (\log{n} + k))$;总的复杂度为 $O(n \times (k + \log{n}))$
149+
* 空间复杂度:$O(n \times k)$
150150

151151
---
152152

LeetCode/2021-2030/2028. 找出缺失的观测数据(中等).md

+5-4
Original file line numberDiff line numberDiff line change
@@ -62,12 +62,13 @@ $k$ 个数字的 平均值 为这些数字求和后再除以 $k$ 。
6262

6363
根据题意,我们需要构造长度为 $n$ 的序列 $ans$,使得 $ans$ 和 $rolls$ 并集的平均值为 $mean$。
6464

65-
由于最终的平均值 $mean$ 已知,我们可以直接算得两序列之和为 $t = (m + n) * mean$。
65+
由于最终的平均值 $mean$ 已知,我们可以直接算得两序列之和为 $t = (m + n) \times mean$。
6666

67-
使用 $t$ 减去 $\sum_{i = 0}^{m}rolls[i]$ 可得 $\sum_{i = 0}^{n}ans[i]$。我们知道一个长度为 $n$ 的有效序列的元素和范围为 $[n, 6 * n]$(骰子编号为 $[1, 6]$),根据 $\sum_{i = 0}^{m}rolls[i]$ 与 $[n, 6 * n]$ 关系进行分情况讨论:
67+
使用 $t$ 减去 $$\sum_{i = 0}^{m}rolls[i]$$ 可得 $$\sum_{i = 0}^{n}ans[i]$$。我们知道一个长度为 $n$ 的有效序列的元素和范围为 $[n, 6 \times n]$(骰子编号为 $[1, 6]$),根据 $\sum_{i = 0}^{m}rolls[i]$ 与 $[n, 6 \times n]$ 关系进行分情况讨论:
6868

69-
* 如果 $\sum_{i = 0}^{n}ans[i]$ 不落在 $[n, 6 * n]$ 范围内,无解,直接返回空数组;
70-
* 如果 $\sum_{i = 0}^{n}ans[i]$ 落在 $[n, 6 * n]$ 范围内,有解,此时尝试构造一个合法的 $ans$ : 起始使用 $\left \lfloor \frac{\sum_{i = 0}^{n}ans[i]}{n} \right \rfloor$ 填充 $ans$,若 $\left \lfloor \frac{\sum_{i = 0}^{n}ans[i]}{n} \right \rfloor * n < \sum_{i = 0}^{n}ans[i]$,计算两者差异值 $d$,并尝试将 $d$ 分摊到前 $d$ 个 $ans[i]$ 上(该过程一定可以顺利进行)。
69+
* 如果 $$\sum_{i = 0}^{n}ans[i]$$ 不落在 $[n, 6 \times n]$ 范围内,无解,直接返回空数组;
70+
71+
* 如果 $$\sum_{i = 0}^{m} rool[i]$$ 落在 $[n, 6 \times n]$ 范围内,有解,此时尝试构造一个合法的 $ans$ : 起始使用 $$\left \lfloor \frac{\sum_{i = 0}^{n}ans[i]}{n} \right \rfloor$$ 填充 $ans$,若 $$\left \lfloor \frac{\sum_{i = 0}^{n}ans[i]}{n} \right \rfloor \times n < \sum_{i = 0}^{n}ans[i]$$,计算两者差异值 $d$,并尝试将 $d$ 分摊到前 $d$ 个 $ans[i]$ 上(该过程一定可以顺利进行)。
7172

7273
代码:
7374
```Java
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
### 题目描述
2+
3+
这是 LeetCode 上的 **[449. 序列化和反序列化二叉搜索树](https://leetcode.cn/problems/serialize-and-deserialize-bst/solution/by-ac_oier-ncwn/)** ,难度为 **中等**
4+
5+
Tag : 「前序遍历」、「BST」
6+
7+
8+
9+
序列化是将数据结构或对象转换为一系列位的过程,以便它可以存储在文件或内存缓冲区中,或通过网络连接链路传输,以便稍后在同一个或另一个计算机环境中重建。
10+
11+
设计一个算法来序列化和反序列化 二叉搜索树 。 对序列化/反序列化算法的工作方式没有限制。 您只需确保二叉搜索树可以序列化为字符串,并且可以将该字符串反序列化为最初的二叉搜索树。
12+
13+
编码的字符串应尽可能紧凑。
14+
15+
示例 1:
16+
```
17+
输入:root = [2,1,3]
18+
19+
输出:[2,1,3]
20+
```
21+
示例 2:
22+
```
23+
输入:root = []
24+
25+
输出:[]
26+
```
27+
28+
提示:
29+
* 树中节点数范围是 $[0, 10^4]$
30+
* $0 <= Node.val <= 10^4$
31+
* 题目数据 保证 输入的树是一棵二叉搜索树。
32+
33+
---
34+
35+
### BST 特性(前序遍历)
36+
37+
实现上,我们可以忽略「BST」这一条件,使用「BFS」或者「直接充当满二叉树」来序列化和反序列化。
38+
39+
但由于点的数量是 $1e4$,最坏情况下是当 BST 成链时,会有较大的空间浪费。
40+
41+
因此,一种较为紧凑的序列化/反序列化的方式是利用「前序遍历 + BST 特性」:
42+
43+
* 序列化:对 BST 进行「前序遍历」,并跳过空节点,节点值通过 `,` 进行分割,假设最终序列化出来的字符串是 `s`
44+
之所以使用「前序遍历」是为了方便反序列化:首先对于某个子树而言,其必然是连续存储,也就是必然能够使用 $s[l,r]$ 所表示处理,同时首位元素必然是该子树的头结点;
45+
46+
* 反序列化:将 `s` 根据分隔符 `,` 进行分割,假设分割后数组 `ss` 长度为 $n$,那么 $ss[0, n - 1]$ 代表完整的子树,我们可以利用「二叉树」特性递归构建,设计递归函数 `TreeNode dfs2(int l, int r, Sring[] ss)`,其含义为利用 $ss[l, r]$ 连续段构造二叉树,并返回头结点:
47+
1. $ss[l]$ 为头结点,其值为 $t$,在 $[l, r]$ 范围内找到第一个比 $t$ 大的位置 $j$:
48+
2. $ss[l]$ 的左子树的所有值均比 $t$ 小,且在 `s` 中连续存储,我们可以递归处理 $[l + 1, j - 1]$ 构建左子树;
49+
3. $ss[l]$ 的右子树的所有值均比 $t$ 大,且在 `s` 中连续存储,我们可以递归处理 $[j, r]$ 构建右子树。
50+
51+
代码:
52+
```Java
53+
public class Codec {
54+
public String serialize(TreeNode root) {
55+
if (root == null) return null;
56+
List<String> list = new ArrayList<>();
57+
dfs1(root, list);
58+
int n = list.size();
59+
StringBuilder sb = new StringBuilder();
60+
for (int i = 0; i < n; i++) {
61+
sb.append(list.get(i));
62+
if (i != n - 1) sb.append(",");
63+
}
64+
return sb.toString();
65+
}
66+
void dfs1(TreeNode root, List<String> list) {
67+
if (root == null) return ;
68+
list.add(String.valueOf(root.val));
69+
dfs1(root.left, list);
70+
dfs1(root.right, list);
71+
}
72+
public TreeNode deserialize(String s) {
73+
if (s == null) return null;
74+
String[] ss = s.split(",");
75+
return dfs2(0, ss.length - 1, ss);
76+
}
77+
TreeNode dfs2(int l, int r, String[] ss) {
78+
if (l > r) return null;
79+
int j = l + 1, t = Integer.parseInt(ss[l]);
80+
TreeNode ans = new TreeNode(t);
81+
while (j <= r && Integer.parseInt(ss[j]) <= t) j++;
82+
ans.left = dfs2(l + 1, j - 1, ss);
83+
ans.right = dfs2(j, r, ss);
84+
return ans;
85+
}
86+
}
87+
```
88+
* 时间复杂度:令节点数量为 $n$,复杂度为 $O(n)$
89+
* 空间复杂度:$O(n)$
90+
91+
---
92+
93+
### 最后
94+
95+
这是我们「刷穿 LeetCode」系列文章的第 `No.449` 篇,系列开始于 2021/01/01,截止于起始日 LeetCode 上共有 1916 道题目,部分是有锁题,我们将先把所有不带锁的题目刷完。
96+
97+
在这个系列文章里面,除了讲解解题思路以外,还会尽可能给出最为简洁的代码。如果涉及通解还会相应的代码模板。
98+
99+
为了方便各位同学能够电脑上进行调试和提交代码,我建立了相关的仓库:https://github.com/SharingSource/LogicStack-LeetCode
100+
101+
在仓库地址里,你可以看到系列文章的题解链接、系列文章的相应代码、LeetCode 原题链接和其他优选题解。
102+

LeetCode/71-80/80. 删除有序数组中的重复项 II(中等).md

+5-9
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,10 @@ Tag : 「双指针」
66

77

88

9-
给你一个有序数组 nums ,请你「原地」删除重复出现的元素,使每个元素 最多出现两次 ,返回删除后数组的新长度。
9+
给你一个有序数组 `nums` ,请你「原地」删除重复出现的元素,使每个元素 最多出现两次 ,返回删除后数组的新长度。
1010

1111
不要使用额外的数组空间,你必须「原地」修改输入数组 并在使用 $O(1)$ 额外空间的条件下完成。
1212

13-
 
14-
1513
说明:
1614

1715
为什么返回数值是整数,但输出的答案是数组呢?
@@ -50,9 +48,9 @@ for (int i = 0; i < len; i++) {
5048

5149
提示:
5250

53-
* 1 <= nums.length <= 3 * $10^4$
54-
* -$10^4$ <= nums[i] <= $10^4$
55-
* nums 已按升序排列
51+
* $1 <= nums.length <= 3 \times 10^4$
52+
* $-10^4 <= nums[i] <= 10^4$
53+
* `nums` 已按升序排列
5654

5755
---
5856

@@ -65,9 +63,7 @@ for (int i = 0; i < len; i++) {
6563
* 由于是保留 `k` 个相同数字,**对于前 `k` 个数字,我们可以直接保留**
6664
* 对于后面的任意数字,能够保留的前提是:**与当前写入的位置前面的第 `k` 个元素进行比较,不相同则保留**
6765

68-
举个🌰,我们令 `k=2`,假设有如下样例
69-
70-
[1,1,1,1,1,1,2,2,2,2,2,2,3]
66+
举个🌰,我们令 `k=2`,假设有如下样例 $[1,1,1,1,1,1,2,2,2,2,2,2,3]$
7167

7268
1. 首先我们先让前 2 位直接保留,得到 1,1
7369
2. 对后面的每一位进行继续遍历,能够保留的前提是与当前位置的前面 `k` 个元素不同(答案中的第一个 1),因此我们会跳过剩余的 1,将第一个 2 追加,得到 1,1,2

0 commit comments

Comments
 (0)