mirror of
https://github.com/krahets/hello-algo.git
synced 2024-12-26 02:06:30 +08:00
build
This commit is contained in:
parent
0760e0865e
commit
902087ec81
23 changed files with 154 additions and 177 deletions
|
@ -494,7 +494,7 @@ elementAddr = firtstElementAddr + elementLength * elementIndex
|
|||
=== "Python"
|
||||
|
||||
```python title="array.py"
|
||||
def insert(nums: list[int], num: int, index: int) -> None:
|
||||
def insert(nums: list[int], num: int, index: int):
|
||||
"""在数组的索引 index 处插入元素 num"""
|
||||
# 把索引 index 以及之后的所有元素向后移动一位
|
||||
for i in range(len(nums) - 1, index, -1):
|
||||
|
@ -649,7 +649,7 @@ elementAddr = firtstElementAddr + elementLength * elementIndex
|
|||
=== "Python"
|
||||
|
||||
```python title="array.py"
|
||||
def remove(nums: list[int], index: int) -> None:
|
||||
def remove(nums: list[int], index: int):
|
||||
"""删除索引 index 处元素"""
|
||||
# 把索引 index 之后的所有元素向前移动一位
|
||||
for i in range(index, len(nums) - 1):
|
||||
|
@ -798,7 +798,7 @@ elementAddr = firtstElementAddr + elementLength * elementIndex
|
|||
=== "Python"
|
||||
|
||||
```python title="array.py"
|
||||
def traverse(nums: list[int]) -> None:
|
||||
def traverse(nums: list[int]):
|
||||
"""遍历数组"""
|
||||
count = 0
|
||||
# 通过索引遍历数组
|
||||
|
|
|
@ -117,8 +117,7 @@ comments: true
|
|||
|
||||
```csharp title=""
|
||||
/* 链表节点类 */
|
||||
class ListNode
|
||||
{
|
||||
class ListNode {
|
||||
int val; // 节点值
|
||||
ListNode next; // 指向下一节点的引用
|
||||
ListNode(int x) => val = x; //构造函数
|
||||
|
@ -400,7 +399,7 @@ comments: true
|
|||
=== "Python"
|
||||
|
||||
```python title="linked_list.py"
|
||||
def insert(n0: ListNode, P: ListNode) -> None:
|
||||
def insert(n0: ListNode, P: ListNode):
|
||||
"""在链表的节点 n0 之后插入节点 P"""
|
||||
n1 = n0.next
|
||||
P.next = n1
|
||||
|
@ -534,7 +533,7 @@ comments: true
|
|||
=== "Python"
|
||||
|
||||
```python title="linked_list.py"
|
||||
def remove(n0: ListNode) -> None:
|
||||
def remove(n0: ListNode):
|
||||
"""删除链表的节点 n0 之后的首个节点"""
|
||||
if not n0.next:
|
||||
return
|
||||
|
|
|
@ -543,15 +543,13 @@ comments: true
|
|||
```csharp title="list.cs"
|
||||
/* 通过索引遍历列表 */
|
||||
int count = 0;
|
||||
for (int i = 0; i < list.Count(); i++)
|
||||
{
|
||||
for (int i = 0; i < list.Count; i++) {
|
||||
count++;
|
||||
}
|
||||
|
||||
/* 直接遍历列表元素 */
|
||||
count = 0;
|
||||
foreach (int n in list)
|
||||
{
|
||||
foreach (int n in list) {
|
||||
count++;
|
||||
}
|
||||
```
|
||||
|
@ -1029,13 +1027,13 @@ comments: true
|
|||
raise IndexError("索引越界")
|
||||
return self.__nums[index]
|
||||
|
||||
def set(self, num: int, index: int) -> None:
|
||||
def set(self, num: int, index: int):
|
||||
"""更新元素"""
|
||||
if index < 0 or index >= self.__size:
|
||||
raise IndexError("索引越界")
|
||||
self.__nums[index] = num
|
||||
|
||||
def add(self, num: int) -> None:
|
||||
def add(self, num: int):
|
||||
"""尾部添加元素"""
|
||||
# 元素数量超出容量时,触发扩容机制
|
||||
if self.size() == self.capacity():
|
||||
|
@ -1043,7 +1041,7 @@ comments: true
|
|||
self.__nums[self.__size] = num
|
||||
self.__size += 1
|
||||
|
||||
def insert(self, num: int, index: int) -> None:
|
||||
def insert(self, num: int, index: int):
|
||||
"""中间插入元素"""
|
||||
if index < 0 or index >= self.__size:
|
||||
raise IndexError("索引越界")
|
||||
|
@ -1070,7 +1068,7 @@ comments: true
|
|||
# 返回被删除元素
|
||||
return num
|
||||
|
||||
def extend_capacity(self) -> None:
|
||||
def extend_capacity(self):
|
||||
"""列表扩容"""
|
||||
# 新建一个长度为原数组 __extend_ratio 倍的新数组,并将原数组拷贝到新数组
|
||||
self.__nums = self.__nums + [0] * self.capacity() * (self.__extend_ratio - 1)
|
||||
|
@ -1583,7 +1581,7 @@ comments: true
|
|||
/* 列表扩容 */
|
||||
public void extendCapacity() {
|
||||
// 新建一个长度为 numsCapacity * extendRatio 的数组,并将原数组拷贝到新数组
|
||||
System.Array.Resize(ref nums, numsCapacity * extendRatio);
|
||||
Array.Resize(ref nums, numsCapacity * extendRatio);
|
||||
// 更新列表容量
|
||||
numsCapacity = nums.Length;
|
||||
}
|
||||
|
|
|
@ -51,7 +51,7 @@ comments: true
|
|||
=== "Python"
|
||||
|
||||
```python title="preorder_traversal_i_compact.py"
|
||||
def pre_order(root: TreeNode) -> None:
|
||||
def pre_order(root: TreeNode):
|
||||
"""前序遍历:例题一"""
|
||||
if root is None:
|
||||
return
|
||||
|
@ -228,7 +228,7 @@ comments: true
|
|||
=== "Python"
|
||||
|
||||
```python title="preorder_traversal_ii_compact.py"
|
||||
def pre_order(root: TreeNode) -> None:
|
||||
def pre_order(root: TreeNode):
|
||||
"""前序遍历:例题二"""
|
||||
if root is None:
|
||||
return
|
||||
|
@ -413,12 +413,9 @@ comments: true
|
|||
|
||||
!!! question "例题三"
|
||||
|
||||
在二叉树中搜索所有值为 $7$ 的节点,请返回根节点到这些节点的路径,**要求路径中只存在一个值为 $7$ 的节点,并且不允许有值为 $3$ 的节点**。
|
||||
在二叉树中搜索所有值为 $7$ 的节点,请返回根节点到这些节点的路径,**并要求路径中不包含值为 $3$ 的节点**。
|
||||
|
||||
在例题二的基础上添加剪枝操作,包括:
|
||||
|
||||
- 当遇到值为 $7$ 的节点时,记录解并返回,停止搜索。
|
||||
- 当遇到值为 $3$ 的节点时,则直接返回,停止搜索。
|
||||
为了满足以上约束条件,**我们需要添加剪枝操作**:在搜索过程中,若遇到值为 $3$ 的节点,则提前返回,停止继续搜索。
|
||||
|
||||
=== "Java"
|
||||
|
||||
|
@ -471,7 +468,7 @@ comments: true
|
|||
=== "Python"
|
||||
|
||||
```python title="preorder_traversal_iii_compact.py"
|
||||
def pre_order(root: TreeNode) -> None:
|
||||
def pre_order(root: TreeNode):
|
||||
"""前序遍历:例题三"""
|
||||
# 剪枝
|
||||
if root is None or root.val == 3:
|
||||
|
@ -631,30 +628,13 @@ comments: true
|
|||
[class]{}-[func]{preOrder}
|
||||
```
|
||||
|
||||
剪枝是一个非常形象的名词。在搜索过程中,**我们利用约束条件“剪掉”了不满足约束条件的搜索分支**,避免许多无意义的尝试,从而提升搜索效率。
|
||||
剪枝是一个非常形象的名词。在搜索过程中,**我们“剪掉”了不满足约束条件的搜索分支**,避免许多无意义的尝试,从而实现搜索效率的提高。
|
||||
|
||||
![根据约束条件剪枝](backtracking_algorithm.assets/preorder_find_constrained_paths.png)
|
||||
|
||||
<p align="center"> Fig. 根据约束条件剪枝 </p>
|
||||
|
||||
## 13.1.3. 常用术语
|
||||
|
||||
为了更清晰地分析算法问题,我们总结一下回溯算法中常用术语的含义,并对照例题三给出对应示例。
|
||||
|
||||
| 名词 | 定义 | 例题三 |
|
||||
| ------------------- | -------------------------------------------------------------------------- | -------------------------------------------------------------------- |
|
||||
| 解 Solution | 解是满足问题特定条件的答案,可能有一个或多个 | 根节点到节点 $7$ 的满足约束条件的所有路径 |
|
||||
| 约束条件 Constraint | 约束条件是问题中限制解的可行性的条件,通常用于剪枝 | 路径中不包含节点 $3$ ,只包含一个节点 $7$ |
|
||||
| 状态 State | 状态表示问题在某一时刻的情况,包括已经做出的选择 | 当前已访问的节点路径,即 `path` 节点列表 |
|
||||
| 尝试 Attempt | 尝试是根据可用选择来探索解空间的过程,包括做出选择,更新状态,检查是否为解 | 递归访问左(右)子节点,将节点添加进 `path` ,判断节点的值是否为 $7$ |
|
||||
| 回退 Backtracking | 回退指遇到不满足约束条件的状态时,撤销前面做出的选择,回到上一个状态 | 当越过叶结点、结束结点访问、遇到值为 $3$ 的节点时终止搜索,函数返回 |
|
||||
| 剪枝 Pruning | 剪枝是根据问题特性和约束条件避免无意义的搜索路径的方法,可提高搜索效率 | 当遇到值为 $3$ 的节点时,则终止继续搜索 |
|
||||
|
||||
!!! tip
|
||||
|
||||
问题、解、状态等概念是通用的,在分治、回溯、动态规划、贪心等算法中都有涉及。
|
||||
|
||||
## 13.1.4. 框架代码
|
||||
## 13.1.3. 框架代码
|
||||
|
||||
接下来,我们尝试将回溯的“尝试、回退、剪枝”的主体框架提炼出来,提升代码的通用性。
|
||||
|
||||
|
@ -669,6 +649,7 @@ comments: true
|
|||
if (isSolution(state)) {
|
||||
// 记录解
|
||||
recordSolution(state, res);
|
||||
// 停止继续搜索
|
||||
return;
|
||||
}
|
||||
// 遍历所有选择
|
||||
|
@ -694,6 +675,7 @@ comments: true
|
|||
if (isSolution(state)) {
|
||||
// 记录解
|
||||
recordSolution(state, res);
|
||||
// 停止继续搜索
|
||||
return;
|
||||
}
|
||||
// 遍历所有选择
|
||||
|
@ -713,12 +695,13 @@ comments: true
|
|||
=== "Python"
|
||||
|
||||
```python title=""
|
||||
def backtrack(state: State, choices: list[choice], res: list[state]) -> None:
|
||||
def backtrack(state: State, choices: list[choice], res: list[state]):
|
||||
"""回溯算法框架"""
|
||||
# 判断是否为解
|
||||
if is_solution(state):
|
||||
# 记录解
|
||||
record_solution(state, res)
|
||||
# 停止继续搜索
|
||||
return
|
||||
# 遍历所有选择
|
||||
for choice in choices:
|
||||
|
@ -740,6 +723,7 @@ comments: true
|
|||
if isSolution(state) {
|
||||
// 记录解
|
||||
recordSolution(state, res)
|
||||
// 停止继续搜索
|
||||
return
|
||||
}
|
||||
// 遍历所有选择
|
||||
|
@ -765,6 +749,7 @@ comments: true
|
|||
if (isSolution(state)) {
|
||||
// 记录解
|
||||
recordSolution(state, res);
|
||||
// 停止继续搜索
|
||||
return;
|
||||
}
|
||||
// 遍历所有选择
|
||||
|
@ -790,6 +775,7 @@ comments: true
|
|||
if (isSolution(state)) {
|
||||
// 记录解
|
||||
recordSolution(state, res);
|
||||
// 停止继续搜索
|
||||
return;
|
||||
}
|
||||
// 遍历所有选择
|
||||
|
@ -815,6 +801,7 @@ comments: true
|
|||
if (isSolution(state)) {
|
||||
// 记录解
|
||||
recordSolution(state, res, numRes);
|
||||
// 停止继续搜索
|
||||
return;
|
||||
}
|
||||
// 遍历所有选择
|
||||
|
@ -840,6 +827,7 @@ comments: true
|
|||
if (isSolution(state)) {
|
||||
// 记录解
|
||||
recordSolution(state, res);
|
||||
// 停止继续搜索
|
||||
return;
|
||||
}
|
||||
// 遍历所有选择
|
||||
|
@ -865,6 +853,7 @@ comments: true
|
|||
if isSolution(state: state) {
|
||||
// 记录解
|
||||
recordSolution(state: state, res: &res)
|
||||
// 停止继续搜索
|
||||
return
|
||||
}
|
||||
// 遍历所有选择
|
||||
|
@ -896,6 +885,7 @@ comments: true
|
|||
if (isSolution(state)) {
|
||||
// 记录解
|
||||
recordSolution(state, res);
|
||||
// 停止继续搜索
|
||||
return;
|
||||
}
|
||||
// 遍历所有选择
|
||||
|
@ -912,7 +902,7 @@ comments: true
|
|||
}
|
||||
```
|
||||
|
||||
下面,我们基于框架代码来解决例题三:状态 `state` 为节点遍历路径,选择 `choices` 为当前节点的左子节点和右子节点,结果 `res` 是路径列表。
|
||||
接下来,我们基于框架代码来解决例题三。状态 `state` 为节点遍历路径,选择 `choices` 为当前节点的左子节点和右子节点,结果 `res` 是路径列表。
|
||||
|
||||
=== "Java"
|
||||
|
||||
|
@ -948,7 +938,6 @@ comments: true
|
|||
if (isSolution(state)) {
|
||||
// 记录解
|
||||
recordSolution(state, res);
|
||||
return;
|
||||
}
|
||||
// 遍历所有选择
|
||||
for (TreeNode choice : choices) {
|
||||
|
@ -999,7 +988,6 @@ comments: true
|
|||
if (isSolution(state)) {
|
||||
// 记录解
|
||||
recordSolution(state, res);
|
||||
return;
|
||||
}
|
||||
// 遍历所有选择
|
||||
for (TreeNode *choice : choices) {
|
||||
|
@ -1048,7 +1036,6 @@ comments: true
|
|||
if is_solution(state):
|
||||
# 记录解
|
||||
record_solution(state, res)
|
||||
return
|
||||
# 遍历所有选择
|
||||
for choice in choices:
|
||||
# 剪枝:检查选择是否合法
|
||||
|
@ -1148,7 +1135,6 @@ comments: true
|
|||
if (isSolution(state)) {
|
||||
// 记录解
|
||||
recordSolution(state, res);
|
||||
return;
|
||||
}
|
||||
// 遍历所有选择
|
||||
for (const choice of choices) {
|
||||
|
@ -1203,7 +1189,6 @@ comments: true
|
|||
if (isSolution(state)) {
|
||||
// 记录解
|
||||
recordSolution(state, res);
|
||||
return;
|
||||
}
|
||||
// 遍历所有选择
|
||||
for (const choice of choices) {
|
||||
|
@ -1270,7 +1255,6 @@ comments: true
|
|||
if (isSolution(state)) {
|
||||
// 记录解
|
||||
recordSolution(state, res);
|
||||
return;
|
||||
}
|
||||
// 遍历所有选择
|
||||
foreach (TreeNode choice in choices) {
|
||||
|
@ -1320,7 +1304,6 @@ comments: true
|
|||
// 检查是否为解
|
||||
if isSolution(state: state) {
|
||||
recordSolution(state: state, res: &res)
|
||||
return
|
||||
}
|
||||
// 遍历所有选择
|
||||
for choice in choices {
|
||||
|
@ -1369,7 +1352,30 @@ comments: true
|
|||
[class]{}-[func]{backtrack}
|
||||
```
|
||||
|
||||
相比基于前序遍历的代码实现,基于回溯算法框架的代码实现虽然显得啰嗦,但通用性更好。实际上,**许多回溯问题都可以在该框架下解决**。我们只需根据具体问题来定义 `state` 和 `choices` ,并实现框架中的各个方法。
|
||||
根据题意,当找到值为 7 的节点后应该继续搜索,**因此我们需要将记录解之后的 `return` 语句删除**。下图对比了保留或删除 `return` 语句的搜索过程。
|
||||
|
||||
![保留与删除 return 的搜索过程对比](backtracking_algorithm.assets/backtrack_remove_return_or_not.png)
|
||||
|
||||
<p align="center"> Fig. 保留与删除 return 的搜索过程对比 </p>
|
||||
|
||||
相比基于前序遍历的代码实现,基于回溯算法框架的代码实现虽然显得啰嗦,但通用性更好。实际上,**许多回溯问题都可以在该框架下解决**。我们只需根据具体问题来定义 `state` 和 `choices` ,并实现框架中的各个方法即可。
|
||||
|
||||
## 13.1.4. 常用术语
|
||||
|
||||
为了更清晰地分析算法问题,我们总结一下回溯算法中常用术语的含义,并对照例题三给出对应示例。
|
||||
|
||||
| 名词 | 定义 | 例题三 |
|
||||
| ------------------- | -------------------------------------------------------------------------- | -------------------------------------------------------------------- |
|
||||
| 解 Solution | 解是满足问题特定条件的答案,可能有一个或多个 | 根节点到节点 $7$ 的满足约束条件的所有路径 |
|
||||
| 约束条件 Constraint | 约束条件是问题中限制解的可行性的条件,通常用于剪枝 | 路径中不包含节点 $3$ ,只包含一个节点 $7$ |
|
||||
| 状态 State | 状态表示问题在某一时刻的情况,包括已经做出的选择 | 当前已访问的节点路径,即 `path` 节点列表 |
|
||||
| 尝试 Attempt | 尝试是根据可用选择来探索解空间的过程,包括做出选择,更新状态,检查是否为解 | 递归访问左(右)子节点,将节点添加进 `path` ,判断节点的值是否为 $7$ |
|
||||
| 回退 Backtracking | 回退指遇到不满足约束条件的状态时,撤销前面做出的选择,回到上一个状态 | 当越过叶结点、结束结点访问、遇到值为 $3$ 的节点时终止搜索,函数返回 |
|
||||
| 剪枝 Pruning | 剪枝是根据问题特性和约束条件避免无意义的搜索路径的方法,可提高搜索效率 | 当遇到值为 $3$ 的节点时,则终止继续搜索 |
|
||||
|
||||
!!! tip
|
||||
|
||||
问题、解、状态等概念是通用的,在分治、回溯、动态规划、贪心等算法中都有涉及。
|
||||
|
||||
## 13.1.5. 优势与局限性
|
||||
|
||||
|
|
|
@ -206,22 +206,19 @@ comments: true
|
|||
|
||||
```csharp title=""
|
||||
/* 类 */
|
||||
class Node
|
||||
{
|
||||
class Node {
|
||||
int val;
|
||||
Node next;
|
||||
Node(int x) { val = x; }
|
||||
}
|
||||
|
||||
/* 函数 */
|
||||
int function()
|
||||
{
|
||||
int function() {
|
||||
// do something...
|
||||
return 0;
|
||||
}
|
||||
|
||||
int algorithm(int n) // 输入数据
|
||||
{
|
||||
int algorithm(int n) { // 输入数据
|
||||
const int a = 0; // 暂存数据(常量)
|
||||
int b = 0; // 暂存数据(变量)
|
||||
Node node = new Node(0); // 暂存数据(对象)
|
||||
|
@ -323,7 +320,7 @@ comments: true
|
|||
=== "Python"
|
||||
|
||||
```python title=""
|
||||
def algorithm(n: int) -> None:
|
||||
def algorithm(n: int):
|
||||
a = 0 # O(1)
|
||||
b = [0] * 10000 # O(1)
|
||||
if n > 10:
|
||||
|
@ -382,12 +379,10 @@ comments: true
|
|||
=== "C#"
|
||||
|
||||
```csharp title=""
|
||||
void algorithm(int n)
|
||||
{
|
||||
void algorithm(int n) {
|
||||
int a = 0; // O(1)
|
||||
int[] b = new int[10000]; // O(1)
|
||||
if (n > 10)
|
||||
{
|
||||
if (n > 10) {
|
||||
int[] nums = new int[n]; // O(n)
|
||||
}
|
||||
}
|
||||
|
@ -472,7 +467,7 @@ comments: true
|
|||
# do something
|
||||
return 0
|
||||
|
||||
def loop(n: int) -> None:
|
||||
def loop(n: int):
|
||||
"""循环 O(1)"""
|
||||
for _ in range(n):
|
||||
function()
|
||||
|
@ -570,22 +565,18 @@ comments: true
|
|||
=== "C#"
|
||||
|
||||
```csharp title=""
|
||||
int function()
|
||||
{
|
||||
int function() {
|
||||
// do something
|
||||
return 0;
|
||||
}
|
||||
/* 循环 O(1) */
|
||||
void loop(int n)
|
||||
{
|
||||
for (int i = 0; i < n; i++)
|
||||
{
|
||||
void loop(int n) {
|
||||
for (int i = 0; i < n; i++) {
|
||||
function();
|
||||
}
|
||||
}
|
||||
/* 递归 O(n) */
|
||||
int recur(int n)
|
||||
{
|
||||
int recur(int n) {
|
||||
if (n == 1) return 1;
|
||||
return recur(n - 1);
|
||||
}
|
||||
|
@ -712,7 +703,7 @@ $$
|
|||
=== "Python"
|
||||
|
||||
```python title="space_complexity.py"
|
||||
def constant(n: int) -> None:
|
||||
def constant(n: int):
|
||||
"""常数阶"""
|
||||
# 常量、变量、对象占用 O(1) 空间
|
||||
a = 0
|
||||
|
@ -951,7 +942,7 @@ $$
|
|||
=== "Python"
|
||||
|
||||
```python title="space_complexity.py"
|
||||
def linear(n: int) -> None:
|
||||
def linear(n: int):
|
||||
"""线性阶"""
|
||||
# 长度为 n 的列表占用 O(n) 空间
|
||||
nums = [0] * n
|
||||
|
@ -1178,7 +1169,7 @@ $$
|
|||
=== "Python"
|
||||
|
||||
```python title="space_complexity.py"
|
||||
def linear_recur(n: int) -> None:
|
||||
def linear_recur(n: int):
|
||||
"""线性阶(递归实现)"""
|
||||
print("递归 n =", n)
|
||||
if n == 1:
|
||||
|
@ -1326,7 +1317,7 @@ $$
|
|||
=== "Python"
|
||||
|
||||
```python title="space_complexity.py"
|
||||
def quadratic(n: int) -> None:
|
||||
def quadratic(n: int):
|
||||
"""平方阶"""
|
||||
# 二维列表占用 O(n^2) 空间
|
||||
num_matrix = [[0] * n for _ in range(n)]
|
||||
|
@ -1568,8 +1559,9 @@ $$
|
|||
return 0;
|
||||
int *nums = malloc(sizeof(int) * n);
|
||||
printf("递归 n = %d 中的 nums 长度 = %d\r\n", n, n);
|
||||
int res = quadraticRecur(n - 1)
|
||||
free(nums);
|
||||
return quadraticRecur(n - 1);
|
||||
return res;
|
||||
}
|
||||
```
|
||||
|
||||
|
|
|
@ -52,7 +52,7 @@ $$
|
|||
|
||||
```python title=""
|
||||
# 在某运行平台下
|
||||
def algorithm(n: int) -> None:
|
||||
def algorithm(n: int):
|
||||
a = 2 # 1 ns
|
||||
a = a + 1 # 1 ns
|
||||
a = a * 2 # 10 ns
|
||||
|
@ -66,12 +66,12 @@ $$
|
|||
```go title=""
|
||||
// 在某运行平台下
|
||||
func algorithm(n int) {
|
||||
a := 2 // 1 ns
|
||||
a = a + 1 // 1 ns
|
||||
a = a * 2 // 10 ns
|
||||
a := 2 // 1 ns
|
||||
a = a + 1 // 1 ns
|
||||
a = a * 2 // 10 ns
|
||||
// 循环 n 次
|
||||
for i := 0; i < n; i++ { // 1 ns
|
||||
fmt.Println(a) // 5 ns
|
||||
for i := 0; i < n; i++ { // 1 ns
|
||||
fmt.Println(a) // 5 ns
|
||||
}
|
||||
}
|
||||
```
|
||||
|
@ -125,15 +125,13 @@ $$
|
|||
|
||||
```csharp title=""
|
||||
// 在某运行平台下
|
||||
void algorithm(int n)
|
||||
{
|
||||
void algorithm(int n) {
|
||||
int a = 2; // 1 ns
|
||||
a = a + 1; // 1 ns
|
||||
a = a * 2; // 10 ns
|
||||
// 循环 n 次
|
||||
for (int i = 0; i < n; i++)
|
||||
{ // 1 ns ,每轮都要执行 i++
|
||||
Console.WriteLine(0); // 5 ns
|
||||
for (int i = 0; i < n; i++) { // 1 ns ,每轮都要执行 i++
|
||||
Console.WriteLine(0); // 5 ns
|
||||
}
|
||||
}
|
||||
```
|
||||
|
@ -232,14 +230,14 @@ $$
|
|||
|
||||
```python title=""
|
||||
# 算法 A 时间复杂度:常数阶
|
||||
def algorithm_A(n: int) -> None:
|
||||
def algorithm_A(n: int):
|
||||
print(0)
|
||||
# 算法 B 时间复杂度:线性阶
|
||||
def algorithm_B(n: int) -> None:
|
||||
def algorithm_B(n: int):
|
||||
for _ in range(n):
|
||||
print(0)
|
||||
# 算法 C 时间复杂度:常数阶
|
||||
def algorithm_C(n: int) -> None:
|
||||
def algorithm_C(n: int):
|
||||
for _ in range(1000000):
|
||||
print(0)
|
||||
```
|
||||
|
@ -333,23 +331,18 @@ $$
|
|||
|
||||
```csharp title=""
|
||||
// 算法 A 时间复杂度:常数阶
|
||||
void algorithm_A(int n)
|
||||
{
|
||||
void algorithm_A(int n) {
|
||||
Console.WriteLine(0);
|
||||
}
|
||||
// 算法 B 时间复杂度:线性阶
|
||||
void algorithm_B(int n)
|
||||
{
|
||||
for (int i = 0; i < n; i++)
|
||||
{
|
||||
void algorithm_B(int n) {
|
||||
for (int i = 0; i < n; i++) {
|
||||
Console.WriteLine(0);
|
||||
}
|
||||
}
|
||||
// 算法 C 时间复杂度:常数阶
|
||||
void algorithm_C(int n)
|
||||
{
|
||||
for (int i = 0; i < 1000000; i++)
|
||||
{
|
||||
void algorithm_C(int n) {
|
||||
for (int i = 0; i < 1000000; i++) {
|
||||
Console.WriteLine(0);
|
||||
}
|
||||
}
|
||||
|
@ -456,7 +449,7 @@ $$
|
|||
=== "Python"
|
||||
|
||||
```python title=""
|
||||
def algorithm(n: int) -> None:
|
||||
def algorithm(n: int):
|
||||
a = 1 # +1
|
||||
a = a + 1 # +1
|
||||
a = a * 2 # +1
|
||||
|
@ -524,14 +517,12 @@ $$
|
|||
=== "C#"
|
||||
|
||||
```csharp title=""
|
||||
void algorithm(int n)
|
||||
{
|
||||
void algorithm(int n) {
|
||||
int a = 1; // +1
|
||||
a = a + 1; // +1
|
||||
a = a * 2; // +1
|
||||
// 循环 n 次
|
||||
for (int i = 0; i < n; i++) // +1(每轮都执行 i ++)
|
||||
{
|
||||
for (int i = 0; i < n; i++) { // +1(每轮都执行 i ++)
|
||||
Console.WriteLine(0); // +1
|
||||
}
|
||||
}
|
||||
|
@ -661,7 +652,7 @@ $$
|
|||
=== "Python"
|
||||
|
||||
```python title=""
|
||||
def algorithm(n: int) -> None:
|
||||
def algorithm(n: int):
|
||||
a = 1 # +0(技巧 1)
|
||||
a = a + n # +0(技巧 1)
|
||||
# +n(技巧 2)
|
||||
|
@ -752,20 +743,16 @@ $$
|
|||
=== "C#"
|
||||
|
||||
```csharp title=""
|
||||
void algorithm(int n)
|
||||
{
|
||||
void algorithm(int n) {
|
||||
int a = 1; // +0(技巧 1)
|
||||
a = a + n; // +0(技巧 1)
|
||||
// +n(技巧 2)
|
||||
for (int i = 0; i < 5 * n + 1; i++)
|
||||
{
|
||||
for (int i = 0; i < 5 * n + 1; i++) {
|
||||
Console.WriteLine(0);
|
||||
}
|
||||
// +n*n(技巧 3)
|
||||
for (int i = 0; i < 2 * n; i++)
|
||||
{
|
||||
for (int j = 0; j < n + 1; j++)
|
||||
{
|
||||
for (int i = 0; i < 2 * n; i++) {
|
||||
for (int j = 0; j < n + 1; j++) {
|
||||
Console.WriteLine(0);
|
||||
}
|
||||
}
|
||||
|
@ -1662,9 +1649,7 @@ $$
|
|||
for (int j = 0; j < i; j++) {
|
||||
if (nums[j] > nums[j + 1]) {
|
||||
// 交换 nums[j] 与 nums[j + 1]
|
||||
int tmp = nums[j];
|
||||
nums[j] = nums[j + 1];
|
||||
nums[j + 1] = tmp;
|
||||
(nums[j + 1], nums[j]) = (nums[j], nums[j + 1]);
|
||||
count += 3; // 元素交换包含 3 个单元操作
|
||||
}
|
||||
}
|
||||
|
|
|
@ -221,7 +221,7 @@ comments: true
|
|||
# 邻接矩阵,行列索引对应“顶点索引”
|
||||
adj_mat: list[list[int]] = []
|
||||
|
||||
def __init__(self, vertices: list[int], edges: list[list[int]]) -> None:
|
||||
def __init__(self, vertices: list[int], edges: list[list[int]]):
|
||||
"""构造方法"""
|
||||
self.vertices: list[int] = []
|
||||
self.adj_mat: list[list[int]] = []
|
||||
|
@ -237,7 +237,7 @@ comments: true
|
|||
"""获取顶点数量"""
|
||||
return len(self.vertices)
|
||||
|
||||
def add_vertex(self, val: int) -> None:
|
||||
def add_vertex(self, val: int):
|
||||
"""添加顶点"""
|
||||
n = self.size()
|
||||
# 向顶点列表中添加新顶点的值
|
||||
|
@ -249,7 +249,7 @@ comments: true
|
|||
for row in self.adj_mat:
|
||||
row.append(0)
|
||||
|
||||
def remove_vertex(self, index: int) -> None:
|
||||
def remove_vertex(self, index: int):
|
||||
"""删除顶点"""
|
||||
if index >= self.size():
|
||||
raise IndexError()
|
||||
|
@ -261,7 +261,7 @@ comments: true
|
|||
for row in self.adj_mat:
|
||||
row.pop(index)
|
||||
|
||||
def add_edge(self, i: int, j: int) -> None:
|
||||
def add_edge(self, i: int, j: int):
|
||||
"""添加边"""
|
||||
# 参数 i, j 对应 vertices 元素索引
|
||||
# 索引越界与相等处理
|
||||
|
@ -271,7 +271,7 @@ comments: true
|
|||
self.adj_mat[i][j] = 1
|
||||
self.adj_mat[j][i] = 1
|
||||
|
||||
def remove_edge(self, i: int, j: int) -> None:
|
||||
def remove_edge(self, i: int, j: int):
|
||||
"""删除边"""
|
||||
# 参数 i, j 对应 vertices 元素索引
|
||||
# 索引越界与相等处理
|
||||
|
@ -280,7 +280,7 @@ comments: true
|
|||
self.adj_mat[i][j] = 0
|
||||
self.adj_mat[j][i] = 0
|
||||
|
||||
def print(self) -> None:
|
||||
def print(self):
|
||||
"""打印邻接矩阵"""
|
||||
print("顶点列表 =", self.vertices)
|
||||
print("邻接矩阵 =")
|
||||
|
@ -1218,7 +1218,7 @@ comments: true
|
|||
class GraphAdjList:
|
||||
"""基于邻接表实现的无向图类"""
|
||||
|
||||
def __init__(self, edges: list[list[Vertex]]) -> None:
|
||||
def __init__(self, edges: list[list[Vertex]]):
|
||||
"""构造方法"""
|
||||
# 邻接表,key: 顶点,value:该顶点的所有邻接顶点
|
||||
self.adj_list = dict[Vertex, Vertex]()
|
||||
|
@ -1232,7 +1232,7 @@ comments: true
|
|||
"""获取顶点数量"""
|
||||
return len(self.adj_list)
|
||||
|
||||
def add_edge(self, vet1: Vertex, vet2: Vertex) -> None:
|
||||
def add_edge(self, vet1: Vertex, vet2: Vertex):
|
||||
"""添加边"""
|
||||
if vet1 not in self.adj_list or vet2 not in self.adj_list or vet1 == vet2:
|
||||
raise ValueError()
|
||||
|
@ -1240,7 +1240,7 @@ comments: true
|
|||
self.adj_list[vet1].append(vet2)
|
||||
self.adj_list[vet2].append(vet1)
|
||||
|
||||
def remove_edge(self, vet1: Vertex, vet2: Vertex) -> None:
|
||||
def remove_edge(self, vet1: Vertex, vet2: Vertex):
|
||||
"""删除边"""
|
||||
if vet1 not in self.adj_list or vet2 not in self.adj_list or vet1 == vet2:
|
||||
raise ValueError()
|
||||
|
@ -1248,14 +1248,14 @@ comments: true
|
|||
self.adj_list[vet1].remove(vet2)
|
||||
self.adj_list[vet2].remove(vet1)
|
||||
|
||||
def add_vertex(self, vet: Vertex) -> None:
|
||||
def add_vertex(self, vet: Vertex):
|
||||
"""添加顶点"""
|
||||
if vet in self.adj_list:
|
||||
return
|
||||
# 在邻接表中添加一个新链表
|
||||
self.adj_list[vet] = []
|
||||
|
||||
def remove_vertex(self, vet: Vertex) -> None:
|
||||
def remove_vertex(self, vet: Vertex):
|
||||
"""删除顶点"""
|
||||
if vet not in self.adj_list:
|
||||
raise ValueError()
|
||||
|
@ -1266,7 +1266,7 @@ comments: true
|
|||
if vet in self.adj_list[vertex]:
|
||||
self.adj_list[vertex].remove(vet)
|
||||
|
||||
def print(self) -> None:
|
||||
def print(self):
|
||||
"""打印邻接表"""
|
||||
print("邻接表 =")
|
||||
for vertex in self.adj_list:
|
||||
|
|
|
@ -1170,7 +1170,7 @@ comments: true
|
|||
if pair not in [None, self.removed]:
|
||||
self.put(pair.key, pair.val)
|
||||
|
||||
def print(self) -> None:
|
||||
def print(self):
|
||||
"""打印哈希表"""
|
||||
for pair in self.buckets:
|
||||
if pair is not None:
|
||||
|
|
|
@ -374,18 +374,15 @@ comments: true
|
|||
```csharp title="hash_map.cs"
|
||||
/* 遍历哈希表 */
|
||||
// 遍历键值对 Key->Value
|
||||
foreach (var kv in map)
|
||||
{
|
||||
foreach (var kv in map) {
|
||||
Console.WriteLine(kv.Key + " -> " + kv.Value);
|
||||
}
|
||||
// 单独遍历键 key
|
||||
foreach (int key in map.Keys)
|
||||
{
|
||||
foreach (int key in map.Keys) {
|
||||
Console.WriteLine(key);
|
||||
}
|
||||
// 单独遍历值 value
|
||||
foreach (String val in map.Values)
|
||||
{
|
||||
foreach (String val in map.Values) {
|
||||
Console.WriteLine(val);
|
||||
}
|
||||
```
|
||||
|
|
|
@ -152,7 +152,7 @@ comments: true
|
|||
return new int[] { i, j };
|
||||
}
|
||||
}
|
||||
return new int[0];
|
||||
return Array.Empty<int>();
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -402,7 +402,7 @@ comments: true
|
|||
}
|
||||
dic.Add(nums[i], i);
|
||||
}
|
||||
return new int[0];
|
||||
return Array.Empty<int>();
|
||||
}
|
||||
```
|
||||
|
||||
|
|
|
@ -84,7 +84,7 @@ comments: true
|
|||
=== "Python"
|
||||
|
||||
```python title="bubble_sort.py"
|
||||
def bubble_sort(nums: list[int]) -> None:
|
||||
def bubble_sort(nums: list[int]):
|
||||
"""冒泡排序"""
|
||||
n = len(nums)
|
||||
# 外循环:未排序区间为 [0, i]
|
||||
|
@ -311,7 +311,7 @@ comments: true
|
|||
=== "Python"
|
||||
|
||||
```python title="bubble_sort.py"
|
||||
def bubble_sort_with_flag(nums: list[int]) -> None:
|
||||
def bubble_sort_with_flag(nums: list[int]):
|
||||
"""冒泡排序(标志优化)"""
|
||||
n = len(nums)
|
||||
# 外循环:未排序区间为 [0, i]
|
||||
|
|
|
@ -86,7 +86,7 @@ comments: true
|
|||
=== "Python"
|
||||
|
||||
```python title="bucket_sort.py"
|
||||
def bucket_sort(nums: list[float]) -> None:
|
||||
def bucket_sort(nums: list[float]):
|
||||
"""桶排序"""
|
||||
# 初始化 k = n/2 个桶,预期向每个桶分配 2 个元素
|
||||
k = len(nums) // 2
|
||||
|
|
|
@ -75,7 +75,7 @@ comments: true
|
|||
=== "Python"
|
||||
|
||||
```python title="counting_sort.py"
|
||||
def counting_sort_naive(nums: list[int]) -> None:
|
||||
def counting_sort_naive(nums: list[int]):
|
||||
"""计数排序"""
|
||||
# 简单实现,无法用于排序对象
|
||||
# 1. 统计数组最大元素 m
|
||||
|
@ -416,7 +416,7 @@ $$
|
|||
=== "Python"
|
||||
|
||||
```python title="counting_sort.py"
|
||||
def counting_sort(nums: list[int]) -> None:
|
||||
def counting_sort(nums: list[int]):
|
||||
"""计数排序"""
|
||||
# 完整实现,可排序对象,并且是稳定排序
|
||||
# 1. 统计数组最大元素 m
|
||||
|
|
|
@ -66,7 +66,7 @@ comments: true
|
|||
=== "Python"
|
||||
|
||||
```python title="insertion_sort.py"
|
||||
def insertion_sort(nums: list[int]) -> None:
|
||||
def insertion_sort(nums: list[int]):
|
||||
"""插入排序"""
|
||||
# 外循环:已排序区间为 [0, i-1]
|
||||
for i in range(1, len(nums)):
|
||||
|
|
|
@ -146,7 +146,7 @@ comments: true
|
|||
=== "Python"
|
||||
|
||||
```python title="merge_sort.py"
|
||||
def merge(nums: list[int], left: int, mid: int, right: int) -> None:
|
||||
def merge(nums: list[int], left: int, mid: int, right: int):
|
||||
"""合并左子数组和右子数组"""
|
||||
# 左子数组区间 [left, mid]
|
||||
# 右子数组区间 [mid + 1, right]
|
||||
|
@ -176,7 +176,7 @@ comments: true
|
|||
nums[k] = tmp[j]
|
||||
j += 1
|
||||
|
||||
def merge_sort(nums: list[int], left: int, right: int) -> None:
|
||||
def merge_sort(nums: list[int], left: int, right: int):
|
||||
"""归并排序"""
|
||||
# 终止条件
|
||||
if left >= right:
|
||||
|
|
|
@ -382,7 +382,7 @@ comments: true
|
|||
=== "Python"
|
||||
|
||||
```python title="quick_sort.py"
|
||||
def quick_sort(self, nums: list[int], left: int, right: int) -> None:
|
||||
def quick_sort(self, nums: list[int], left: int, right: int):
|
||||
"""快速排序"""
|
||||
# 子数组长度为 1 时终止递归
|
||||
if left >= right:
|
||||
|
@ -1027,7 +1027,7 @@ comments: true
|
|||
=== "Python"
|
||||
|
||||
```python title="quick_sort.py"
|
||||
def quick_sort(self, nums: list[int], left: int, right: int) -> None:
|
||||
def quick_sort(self, nums: list[int], left: int, right: int):
|
||||
"""快速排序(尾递归优化)"""
|
||||
# 子数组长度为 1 时终止
|
||||
while left < right:
|
||||
|
|
|
@ -141,7 +141,7 @@ $$
|
|||
# 传入 exp 而非 k 可以避免在此重复执行昂贵的次方计算
|
||||
return (num // exp) % 10
|
||||
|
||||
def counting_sort_digit(nums: list[int], exp: int) -> None:
|
||||
def counting_sort_digit(nums: list[int], exp: int):
|
||||
"""计数排序(根据 nums 第 k 位排序)"""
|
||||
# 十进制的位范围为 0~9 ,因此需要长度为 10 的桶
|
||||
counter = [0] * 10
|
||||
|
@ -164,7 +164,7 @@ $$
|
|||
for i in range(n):
|
||||
nums[i] = res[i]
|
||||
|
||||
def radix_sort(nums: list[int]) -> None:
|
||||
def radix_sort(nums: list[int]):
|
||||
"""基数排序"""
|
||||
# 获取数组的最大元素,用于判断最大位数
|
||||
m = max(nums)
|
||||
|
|
|
@ -625,7 +625,7 @@ comments: true
|
|||
class ListNode:
|
||||
"""双向链表节点"""
|
||||
|
||||
def __init__(self, val: int) -> None:
|
||||
def __init__(self, val: int):
|
||||
"""构造方法"""
|
||||
self.val: int = val
|
||||
self.next: ListNode | None = None # 后继节点引用(指针)
|
||||
|
@ -634,7 +634,7 @@ comments: true
|
|||
class LinkedListDeque:
|
||||
"""基于双向链表实现的双向队列"""
|
||||
|
||||
def __init__(self) -> None:
|
||||
def __init__(self):
|
||||
"""构造方法"""
|
||||
self.front: ListNode | None = None # 头节点 front
|
||||
self.rear: ListNode | None = None # 尾节点 rear
|
||||
|
@ -648,7 +648,7 @@ comments: true
|
|||
"""判断双向队列是否为空"""
|
||||
return self.size() == 0
|
||||
|
||||
def push(self, num: int, is_front: bool) -> None:
|
||||
def push(self, num: int, is_front: bool):
|
||||
"""入队操作"""
|
||||
node = ListNode(num)
|
||||
# 若链表为空,则令 front, rear 都指向 node
|
||||
|
@ -668,11 +668,11 @@ comments: true
|
|||
self.rear = node # 更新尾节点
|
||||
self.__size += 1 # 更新队列长度
|
||||
|
||||
def push_first(self, num: int) -> None:
|
||||
def push_first(self, num: int):
|
||||
"""队首入队"""
|
||||
self.push(num, True)
|
||||
|
||||
def push_last(self, num: int) -> None:
|
||||
def push_last(self, num: int):
|
||||
"""队尾入队"""
|
||||
self.push(num, False)
|
||||
|
||||
|
@ -2042,7 +2042,7 @@ comments: true
|
|||
class ArrayDeque:
|
||||
"""基于环形数组实现的双向队列"""
|
||||
|
||||
def __init__(self, capacity: int) -> None:
|
||||
def __init__(self, capacity: int):
|
||||
"""构造方法"""
|
||||
self.__nums: list[int] = [0] * capacity
|
||||
self.__front: int = 0
|
||||
|
@ -2067,7 +2067,7 @@ comments: true
|
|||
# 当 i 越过数组头部后,回到尾部
|
||||
return (i + self.capacity()) % self.capacity()
|
||||
|
||||
def push_first(self, num: int) -> None:
|
||||
def push_first(self, num: int):
|
||||
"""队首入队"""
|
||||
if self.__size == self.capacity():
|
||||
print("双向队列已满")
|
||||
|
@ -2079,7 +2079,7 @@ comments: true
|
|||
self.__nums[self.__front] = num
|
||||
self.__size += 1
|
||||
|
||||
def push_last(self, num: int) -> None:
|
||||
def push_last(self, num: int):
|
||||
"""队尾入队"""
|
||||
if self.__size == self.capacity():
|
||||
print("双向队列已满")
|
||||
|
|
|
@ -218,10 +218,10 @@ comments: true
|
|||
int pop = queue.Dequeue();
|
||||
|
||||
/* 获取队列的长度 */
|
||||
int size = queue.Count();
|
||||
int size = queue.Count;
|
||||
|
||||
/* 判断队列是否为空 */
|
||||
bool isEmpty = queue.Count() == 0;
|
||||
bool isEmpty = queue.Count == 0;
|
||||
```
|
||||
|
||||
=== "Swift"
|
||||
|
@ -471,7 +471,7 @@ comments: true
|
|||
"""判断队列是否为空"""
|
||||
return not self.__front
|
||||
|
||||
def push(self, num: int) -> None:
|
||||
def push(self, num: int):
|
||||
"""入队"""
|
||||
# 尾节点后添加 num
|
||||
node = ListNode(num)
|
||||
|
@ -1272,7 +1272,7 @@ comments: true
|
|||
class ArrayQueue:
|
||||
"""基于环形数组实现的队列"""
|
||||
|
||||
def __init__(self, size: int) -> None:
|
||||
def __init__(self, size: int):
|
||||
"""构造方法"""
|
||||
self.__nums: list[int] = [0] * size # 用于存储队列元素的数组
|
||||
self.__front: int = 0 # 队首指针,指向队首元素
|
||||
|
@ -1290,7 +1290,7 @@ comments: true
|
|||
"""判断队列是否为空"""
|
||||
return self.__size == 0
|
||||
|
||||
def push(self, num: int) -> None:
|
||||
def push(self, num: int):
|
||||
"""入队"""
|
||||
if self.__size == self.capacity():
|
||||
raise IndexError("队列已满")
|
||||
|
|
|
@ -217,10 +217,10 @@ comments: true
|
|||
int pop = stack.Pop();
|
||||
|
||||
/* 获取栈的长度 */
|
||||
int size = stack.Count();
|
||||
int size = stack.Count;
|
||||
|
||||
/* 判断是否为空 */
|
||||
bool isEmpty = stack.Count()==0;
|
||||
bool isEmpty = stack.Count == 0;
|
||||
```
|
||||
|
||||
=== "Swift"
|
||||
|
@ -451,7 +451,7 @@ comments: true
|
|||
"""判断栈是否为空"""
|
||||
return not self.__peek
|
||||
|
||||
def push(self, val: int) -> None:
|
||||
def push(self, val: int):
|
||||
"""入栈"""
|
||||
node = ListNode(val)
|
||||
node.next = self.__peek
|
||||
|
@ -1102,7 +1102,7 @@ comments: true
|
|||
class ArrayStack:
|
||||
"""基于数组实现的栈"""
|
||||
|
||||
def __init__(self) -> None:
|
||||
def __init__(self):
|
||||
"""构造方法"""
|
||||
self.__stack: list[int] = []
|
||||
|
||||
|
@ -1114,7 +1114,7 @@ comments: true
|
|||
"""判断栈是否为空"""
|
||||
return self.__stack == []
|
||||
|
||||
def push(self, item: int) -> None:
|
||||
def push(self, item: int):
|
||||
"""入栈"""
|
||||
self.__stack.append(item)
|
||||
|
||||
|
|
|
@ -1448,7 +1448,7 @@ AVL 树的特点在于「旋转 Rotation」操作,它能够在不影响二叉
|
|||
=== "Python"
|
||||
|
||||
```python title="avl_tree.py"
|
||||
def insert(self, val) -> None:
|
||||
def insert(self, val):
|
||||
"""插入节点"""
|
||||
self.root = self.__insert_helper(self.root, val)
|
||||
|
||||
|
@ -1797,7 +1797,7 @@ AVL 树的特点在于「旋转 Rotation」操作,它能够在不影响二叉
|
|||
=== "Python"
|
||||
|
||||
```python title="avl_tree.py"
|
||||
def remove(self, val: int) -> None:
|
||||
def remove(self, val: int):
|
||||
"""删除节点"""
|
||||
self.root = self.__remove_helper(self.root, val)
|
||||
|
||||
|
|
|
@ -349,7 +349,7 @@ comments: true
|
|||
=== "Python"
|
||||
|
||||
```python title="binary_search_tree.py"
|
||||
def insert(self, num: int) -> None:
|
||||
def insert(self, num: int):
|
||||
"""插入节点"""
|
||||
# 若树为空,直接提前返回
|
||||
if self.root is None:
|
||||
|
@ -769,7 +769,7 @@ comments: true
|
|||
=== "Python"
|
||||
|
||||
```python title="binary_search_tree.py"
|
||||
def remove(self, num: int) -> None:
|
||||
def remove(self, num: int):
|
||||
"""删除节点"""
|
||||
# 若树为空,直接提前返回
|
||||
if self.root is None:
|
||||
|
|
|
@ -385,7 +385,7 @@ comments: true
|
|||
=== "Python"
|
||||
|
||||
```python title="binary_tree_dfs.py"
|
||||
def pre_order(root: TreeNode | None) -> None:
|
||||
def pre_order(root: TreeNode | None):
|
||||
"""前序遍历"""
|
||||
if root is None:
|
||||
return
|
||||
|
@ -394,7 +394,7 @@ comments: true
|
|||
pre_order(root=root.left)
|
||||
pre_order(root=root.right)
|
||||
|
||||
def in_order(root: TreeNode | None) -> None:
|
||||
def in_order(root: TreeNode | None):
|
||||
"""中序遍历"""
|
||||
if root is None:
|
||||
return
|
||||
|
@ -403,7 +403,7 @@ comments: true
|
|||
res.append(root.val)
|
||||
in_order(root=root.right)
|
||||
|
||||
def post_order(root: TreeNode | None) -> None:
|
||||
def post_order(root: TreeNode | None):
|
||||
"""后序遍历"""
|
||||
if root is None:
|
||||
return
|
||||
|
|
Loading…
Reference in a new issue