This commit is contained in:
krahets 2023-03-23 18:56:56 +08:00
parent 2715ce703a
commit 0dfdcf0bab
25 changed files with 118 additions and 115 deletions

View file

@ -149,7 +149,7 @@ elementAddr = firtstElementAddr + elementLength * elementIndex
=== "Python"
```python title="array.py"
def random_access(nums: List[int]) -> int:
def random_access(nums: list[int]) -> int:
""" 随机访问元素 """
# 在区间 [0, len(nums)-1] 中随机抽取一个数字
random_index = random.randint(0, len(nums) - 1)
@ -285,7 +285,7 @@ elementAddr = firtstElementAddr + elementLength * elementIndex
=== "Python"
```python title="array.py"
def extend(nums: List[int], enlarge: int) -> List[int]:
def extend(nums: list[int], enlarge: int) -> list[int]:
""" 扩展数组长度 """
# 初始化一个扩展长度后的数组
res = [0] * (len(nums) + enlarge)
@ -440,7 +440,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) -> None:
""" 在数组的索引 index 处插入元素 num """
# 把索引 index 以及之后的所有元素向后移动一位
for i in range(len(nums) - 1, index, -1):
@ -560,7 +560,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) -> None:
""" 删除索引 index 处元素 """
# 把索引 index 之后的所有元素向前移动一位
for i in range(index, len(nums) - 1):
@ -692,7 +692,7 @@ elementAddr = firtstElementAddr + elementLength * elementIndex
=== "Python"
```python title="array.py"
def traverse(nums: List[int]) -> None:
def traverse(nums: list[int]) -> None:
""" 遍历数组 """
count = 0
# 通过索引遍历数组
@ -848,7 +848,7 @@ elementAddr = firtstElementAddr + elementLength * elementIndex
=== "Python"
```python title="array.py"
def find(nums: List[int], target: int) -> int:
def find(nums: list[int], target: int) -> int:
""" 在数组中查找指定元素 """
for i in range(len(nums)):
if nums[i] == target:

View file

@ -632,7 +632,7 @@ comments: true
=== "Python"
```python title="linked_list.py"
def access(head: ListNode, index: int) -> Optional[ListNode]:
def access(head: ListNode, index: int) -> ListNode | None:
""" 访问链表中索引为 index 的结点 """
for _ in range(index):
if not head:

View file

@ -938,7 +938,7 @@ comments: true
def __init__(self):
""" 构造方法 """
self.__capacity: int = 10 # 列表容量
self.__nums: List[int] = [0] * self.__capacity # 数组(存储列表元素)
self.__nums: my_list[int] = [0] * self.__capacity # 数组(存储列表元素)
self.__size: int = 0 # 列表长度(即当前元素数量)
self.__extend_ratio: int = 2 # 每次列表扩容的倍数
@ -1001,7 +1001,7 @@ comments: true
# 更新列表容量
self.__capacity = len(self.__nums)
def to_array(self) -> List[int]:
def to_array(self) -> list[int]:
""" 返回有效长度的列表 """
return self.__nums[:self.__size]
```

View file

@ -629,7 +629,7 @@ $$
""" 常数阶 """
# 常量、变量、对象占用 O(1) 空间
a: int = 0
nums: List[int] = [0] * 10000
nums: list[int] = [0] * 10000
node = ListNode(0)
# 循环中的变量占用 O(1) 空间
for _ in range(n):
@ -833,9 +833,9 @@ $$
def linear(n: int) -> None:
""" 线性阶 """
# 长度为 n 的列表占用 O(n) 空间
nums: List[int] = [0] * n
nums: list[int] = [0] * n
# 长度为 n 的哈希表占用 O(n) 空间
mapp: Dict = {}
mapp = dict[int, str]()
for i in range(n):
mapp[i] = str(i)
```
@ -1131,7 +1131,7 @@ $$
def quadratic(n: int) -> None:
""" 平方阶 """
# 二维列表占用 O(n^2) 空间
num_matrix: List[List[int]] = [[0] * n for _ in range(n)]
num_matrix: list[list[int]] = [[0] * n for _ in range(n)]
```
=== "Go"
@ -1280,7 +1280,7 @@ $$
""" 平方阶(递归实现) """
if n <= 0: return 0
# 数组 nums 长度为 n, n-1, ..., 2, 1
nums: List[int] = [0] * n
nums: list[int] = [0] * n
return quadratic_recur(n - 1)
```
@ -1406,7 +1406,7 @@ $$
=== "Python"
```python title="space_complexity.py"
def build_tree(n: int) -> Optional[TreeNode]:
def build_tree(n: int) -> TreeNode | None:
""" 指数阶(建立满二叉树) """
if n == 0: return None
root = TreeNode(0)

View file

@ -65,7 +65,7 @@ comments: true
=== "Python"
```python title="leetcode_two_sum.py"
def two_sum_brute_force(nums: List[int], target: int) -> List[int]:
def two_sum_brute_force(nums: list[int], target: int) -> list[int]:
""" 方法一:暴力枚举 """
# 两层循环,时间复杂度 O(n^2)
for i in range(len(nums) - 1):
@ -242,7 +242,7 @@ comments: true
=== "Python"
```python title="leetcode_two_sum.py"
def two_sum_hash_table(nums: List[int], target: int) -> List[int]:
def two_sum_hash_table(nums: list[int], target: int) -> list[int]:
""" 方法二:辅助哈希表 """
# 辅助哈希表,空间复杂度 O(n)
dic = {}

View file

@ -1075,7 +1075,7 @@ $$
=== "Python"
```python title="time_complexity.py"
def array_traversal(nums: List[int]) -> int:
def array_traversal(nums: list[int]) -> int:
""" 线性阶(遍历数组)"""
count: int = 0
# 循环次数与数组长度成正比
@ -1391,7 +1391,7 @@ $$
=== "Python"
```python title="time_complexity.py"
def bubble_sort(nums: List[int]) -> int:
def bubble_sort(nums: list[int]) -> int:
""" 平方阶(冒泡排序)"""
count: int = 0 # 计数器
# 外循环:待排序元素数量为 n-1, n-2, ..., 1
@ -2481,15 +2481,15 @@ $$
=== "Python"
```python title="worst_best_time_complexity.py"
def random_numbers(n: int) -> List[int]:
def random_numbers(n: int) -> list[int]:
""" 生成一个数组,元素为: 1, 2, ..., n ,顺序被打乱 """
# 生成数组 nums =: 1, 2, 3, ..., n
nums: List[int] = [i for i in range(1, n + 1)]
nums: list[int] = [i for i in range(1, n + 1)]
# 随机打乱数组元素
random.shuffle(nums)
return nums
def find_one(nums: List[int]) -> int:
def find_one(nums: list[int]) -> int:
""" 查找数组 nums 中数字 1 所在索引 """
for i in range(len(nums)):
# 当元素 1 在数组头部时,达到最佳时间复杂度 O(1)

View file

@ -216,14 +216,14 @@ comments: true
class GraphAdjMat:
""" 基于邻接矩阵实现的无向图类 """
# 顶点列表,元素代表“顶点值”,索引代表“顶点索引”
vertices: List[int] = []
vertices: list[int] = []
# 邻接矩阵,行列索引对应“顶点索引”
adj_mat: List[List[int]] = []
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]]) -> None:
""" 构造方法 """
self.vertices: List[int] = []
self.adj_mat: List[List[int]] = []
self.vertices: list[int] = []
self.adj_mat: list[list[int]] = []
# 添加顶点
for val in vertices:
self.add_vertex(val)
@ -967,10 +967,10 @@ comments: true
```python title="graph_adjacency_list.py"
class GraphAdjList:
""" 基于邻接表实现的无向图类 """
def __init__(self, edges: List[List[Vertex]]) -> None:
def __init__(self, edges: list[list[Vertex]]) -> None:
""" 构造方法 """
# 邻接表key: 顶点value该顶点的所有邻接顶点
self.adj_list: Dict = {}
self.adj_list = dict[Vertex, Vertex]()
# 添加所有顶点和边
for edge in edges:
self.add_vertex(edge[0])

View file

@ -93,15 +93,15 @@ BFS 常借助「队列」来实现。队列具有“先入先出”的性质,
=== "Python"
```python title="graph_bfs.py"
def graph_bfs(graph: GraphAdjList, start_vet: Vertex) -> List[Vertex]:
def graph_bfs(graph: GraphAdjList, start_vet: Vertex) -> list[Vertex]:
""" 广度优先遍历 BFS """
# 使用邻接表来表示图,以便获取指定顶点的所有邻接顶点
# 顶点遍历序列
res = []
# 哈希表,用于记录已被访问过的顶点
visited = set([start_vet])
visited = set[Vertex]([start_vet])
# 队列用于实现 BFS
que = collections.deque([start_vet])
que = deque[Vertex]([start_vet])
# 以顶点 vet 为起点,循环直至访问完所有顶点
while len(que) > 0:
vet = que.popleft() # 队首顶点出队
@ -378,7 +378,7 @@ BFS 常借助「队列」来实现。队列具有“先入先出”的性质,
=== "Python"
```python title="graph_dfs.py"
def dfs(graph: GraphAdjList, visited: Set[Vertex], res: List[Vertex], vet: Vertex):
def dfs(graph: GraphAdjList, visited: set[Vertex], res: list[Vertex], vet: Vertex):
""" 深度优先遍历 DFS 辅助函数 """
res.append(vet) # 记录访问顶点
visited.add(vet) # 标记该顶点已被访问
@ -389,12 +389,12 @@ BFS 常借助「队列」来实现。队列具有“先入先出”的性质,
# 递归访问邻接顶点
dfs(graph, visited, res, adjVet)
def graph_dfs(graph: GraphAdjList, start_vet: Vertex) -> List[Vertex]:
def graph_dfs(graph: GraphAdjList, start_vet: Vertex) -> list[Vertex]:
""" 深度优先遍历 DFS """
# 顶点遍历序列
res = []
# 哈希表,用于记录已被访问过的顶点
visited = set()
visited = set[Vertex]()
dfs(graph, visited, res, start_vet)
return res
```

View file

@ -617,7 +617,7 @@ $$
def __init__(self):
""" 构造方法 """
# 初始化数组,包含 100 个桶
self.buckets: List[Optional[Entry]] = [None] * 100
self.buckets: list[Entry | None] = [None] * 100
def hash_func(self, key: int) -> int:
""" 哈希函数 """
@ -644,25 +644,25 @@ $$
# 置为 None ,代表删除
self.buckets[index] = None
def entry_set(self) -> List[Entry]:
def entry_set(self) -> list[Entry]:
""" 获取所有键值对 """
result: List[Entry] = []
result: list[Entry] = []
for pair in self.buckets:
if pair is not None:
result.append(pair)
return result
def key_set(self) -> List[int]:
def key_set(self) -> list[int]:
""" 获取所有键 """
result: List[int] = []
result: list[int] = []
for pair in self.buckets:
if pair is not None:
result.append(pair.key)
return result
def value_set(self) -> List[str]:
def value_set(self) -> list[str]:
""" 获取所有值 """
result: List[str] = []
result: list[str] = []
for pair in self.buckets:
if pair is not None:
result.append(pair.val)

View file

@ -49,7 +49,7 @@ comments: true
=== "Python"
```python title="my_heap.py"
def __init__(self, nums: List[int]):
def __init__(self, nums: list[int]):
""" 构造方法 """
# 将列表元素原封不动添加进堆
self.max_heap = nums

View file

@ -98,7 +98,7 @@ $$
=== "Python"
```python title="binary_search.py"
def binary_search(nums: List[int], target: int) -> int:
def binary_search(nums: list[int], target: int) -> int:
""" 二分查找(双闭区间) """
# 初始化双闭区间 [0, n-1] ,即 i, j 分别指向数组首元素、尾元素
i, j = 0, len(nums) - 1
@ -309,7 +309,7 @@ $$
=== "Python"
```python title="binary_search.py"
def binary_search1(nums: List[int], target: int) -> int:
def binary_search1(nums: list[int], target: int) -> int:
""" 二分查找(左闭右开) """
# 初始化左闭右开 [0, n) ,即 i, j 分别指向数组首元素、尾元素+1
i, j = 0, len(nums)

View file

@ -45,7 +45,7 @@ comments: true
=== "Python"
```python title="hashing_search.py"
def hashing_search_array(mapp: Dict[int, int], target: int) -> int:
def hashing_search_array(mapp: dict[int, int], target: int) -> int:
""" 哈希查找(数组) """
# 哈希表的 key: 目标元素value: 索引
# 若哈希表中无此 key ,返回 -1
@ -163,7 +163,7 @@ comments: true
=== "Python"
```python title="hashing_search.py"
def hashing_search_linkedlist(mapp: Dict[int, ListNode], target: int) -> Optional[ListNode]:
def hashing_search_linkedlist(mapp: dict[int, ListNode], target: int) -> ListNode | None:
""" 哈希查找(链表) """
# 哈希表的 key: 目标元素value: 结点对象
# 若哈希表中无此 key ,返回 None

View file

@ -49,7 +49,7 @@ comments: true
=== "Python"
```python title="linear_search.py"
def linear_search_array(nums: List[int], target: int) -> int:
def linear_search_array(nums: list[int], target: int) -> int:
""" 线性查找(数组) """
# 遍历数组
for i in range(len(nums)):
@ -206,7 +206,7 @@ comments: true
=== "Python"
```python title="linear_search.py"
def linear_search_linkedlist(head: ListNode, target: int) -> Optional[ListNode]:
def linear_search_linkedlist(head: ListNode, target: int) -> ListNode | None:
""" 线性查找(链表) """
# 遍历链表
while head:

View file

@ -87,7 +87,7 @@ comments: true
=== "Python"
```python title="bubble_sort.py"
def bubble_sort(nums: List[int]) -> None:
def bubble_sort(nums: list[int]) -> None:
""" 冒泡排序 """
n: int = len(nums)
# 外循环:待排序元素数量为 n-1, n-2, ..., 1
@ -295,7 +295,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]) -> None:
""" 冒泡排序(标志优化) """
n: int = len(nums)
# 外循环:待排序元素数量为 n-1, n-2, ..., 1

View file

@ -1,16 +1,20 @@
## 拓展到桶排序
# 桶排序
如果我们把上述 `bucket` 中的每个索引想象成一个桶,那么可以将计数排序理解为把 $n$ 个元素分配到对应的桶中,再根据桶与桶之间天然的有序性来实现排序
「桶排序 Bucket Sort」考虑设置 $k$ 个桶,并将 $n$ 个元素根据大小分配到 $k$ 个桶中,**并在每个桶内部分别执行排序**,由于桶之间的大小关系的确定的,因此最后按照桶之间的顺序将元素依次展开即可
以上解读便是「桶排序 Bucket Sort」的核心思想。具体地桶排序考虑将 $n$ 个元素根据大小范围均匀地分配到 $k$ 个桶中,由于桶之间是有序的,**因此仅需在每个桶内部执行排序**,最终按照桶之间的大小关系将元素依次排列,即可得到排序结果
假设元素平均分布在各个桶内,则每个桶内元素数量为 $\frac{n}{k}$ ;如果使用「快速排序」来实现桶内排序,则排序单个桶使用 $O(\frac{n}{k} \log\frac{n}{k})$ 时间,排序所有桶使用 $O(n \log\frac{n}{k})$ 时间。**当桶数量 $k$ 比较大时,时间复杂度则趋向于 $O(n)$**
假设使用「快速排序」来排序各个桶内的元素,每个桶内元素数量为 $\frac{n}{k}$ ,则排序单个桶使用 $O(\frac{n}{k} \log\frac{n}{k})$ 时间,排序所有桶使用 $O(n \log\frac{n}{k})$ 时间。**当桶数量 $k$ 接近 $n$ 时,时间复杂度则趋向于 $O(n)$** 。
!!! note 计数排序与桶排序的关系
**计数排序可以看作是桶排序的一种特例**。我们可以把计数排序中 `counter` 的每个索引想象成一个桶,将统计数量的过程想象成把 $n$ 个元素分配到对应的桶中,再根据桶之间的有序性输出结果,从而实现排序。
(图)
理论上桶排序的时间复杂度是 $O(n)$ **但前提是需要将元素均匀分配到各个桶中**,而这是不太容易做到的。假设我们要把淘宝中的 $100$ 万件商品根据价格范围平均分配到 $100$ 个桶中,由于商品价格不是均匀分布的,比如 $1$ ~ $100$ 元的商品非常多、$1$ 万元以上的商品非常少等,因此难以简单地设定各个桶的价格分界线。解决方案有
理论上桶排序的时间复杂度是 $O(n)$ **但前提是需要将元素均匀分配到各个桶中**,而这并不容易做到。假设想要把淘宝的 $100$ 万件商品根据价格范围平均分配到 $100$ 个桶中,而商品价格不是均匀分布的,例如 $100$ 元以下的商品非常多、$1000$ 元以上的商品非常少等。如果我们将价格区间平均划分为 $100$ 份,那么各个桶内的商品数量差距会非常大。为了实现平均分配,我们一般这样做
- 先初步设置一个分界线,将元素分配完后,**把元素较多的桶继续划分为多个桶**,直至每个桶内元素数量合理为止;该做法一般使用递归实现
- 如果我们提前知道商品价格的概率分布,**则可以根据已知分布来设置每个桶的价格分界线**;值得说明的是,数据分布不一定需要 case-by-case 地统计,有时可以采用一些常见分布来近似,例如自然界的正态分布
- 先粗略设置分界线,将元素分配完后,**把元素较多的桶继续划分为多个桶**,直至所有桶内元素数量合理为止;该做法本质上是一个递归树
- 如果我们提前知道商品价格的概率分布,**则可以根据已知分布来设置每个桶的价格分界线**;值得说明的是,数据分布不一定需要特意统计,也可以根据数据特点采用某种常见概率模型来近似,例如自然界的正态分布等
(图)
另外,排序桶内元素需要选择一种合适的排序算法,比如快速排序。

View file

@ -77,7 +77,7 @@ comments: true
=== "Python"
```python title="counting_sort.py"
def counting_sort_naive(nums: List[int]) -> None:
def counting_sort_naive(nums: list[int]) -> None:
""" 计数排序 """
# 简单实现,无法用于排序对象
# 1. 统计数组最大元素 m
@ -301,7 +301,7 @@ $$
=== "Python"
```python title="counting_sort.py"
def counting_sort(nums: List[int]) -> None:
def counting_sort(nums: list[int]) -> None:
""" 计数排序 """
# 完整实现,可排序对象,并且是稳定排序
# 1. 统计数组最大元素 m

View file

@ -63,7 +63,7 @@ comments: true
=== "Python"
```python title="insertion_sort.py"
def insertion_sort(nums: List[int]) -> None:
def insertion_sort(nums: list[int]) -> None:
""" 插入排序 """
# 外循环base = nums[1], nums[2], ..., nums[n-1]
for i in range(1, len(nums)):

View file

@ -146,12 +146,12 @@ 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) -> None:
""" 合并左子数组和右子数组 """
# 左子数组区间 [left, mid]
# 右子数组区间 [mid + 1, right]
# 初始化辅助数组 借助 copy模块
tmp: List[int] = nums[left:right + 1].copy()
# 初始化辅助数组
tmp: list[int] = list(nums[left:right + 1])
# 左子数组的起始索引和结束索引
left_start: int = 0
left_end: int = mid - left
@ -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) -> None:
""" 归并排序 """
# 终止条件
if left >= right:

View file

@ -100,7 +100,7 @@ comments: true
=== "Python"
```python title="quick_sort.py"
def partition(self, nums: List[int], left: int, right: int) -> int:
def partition(self, nums: list[int], left: int, right: int) -> int:
""" 哨兵划分 """
# 以 nums[left] 作为基准数
i, j = left, right
@ -343,7 +343,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) -> None:
""" 快速排序 """
# 子数组长度为 1 时终止递归
if left >= right:
@ -562,7 +562,7 @@ comments: true
=== "Python"
```python title="quick_sort.py"
def median_three(self, nums: List[int], left: int, mid: int, right: int) -> int:
def median_three(self, nums: list[int], left: int, mid: int, right: int) -> int:
""" 选取三个元素的中位数 """
# 此处使用异或运算来简化代码
# 异或规则为 0 ^ 0 = 1 ^ 1 = 0, 0 ^ 1 = 1 ^ 0 = 1
@ -572,7 +572,7 @@ comments: true
return mid
return right
def partition(self, nums: List[int], left: int, right: int) -> int:
def partition(self, nums: list[int], left: int, right: int) -> int:
""" 哨兵划分(三数取中值) """
# 以 nums[left] 作为基准数
med: int = self.median_three(nums, left, (left + right) // 2, right)
@ -855,7 +855,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) -> None:
""" 快速排序(尾递归优化) """
# 子数组长度为 1 时终止
while left < right:

View file

@ -595,15 +595,15 @@ comments: true
def __init__(self, val: int) -> None:
""" 构造方法 """
self.val: int = val
self.next: Optional[ListNode] = None # 后继结点引用(指针)
self.prev: Optional[ListNode] = None # 前驱结点引用(指针)
self.next: ListNode | None = None # 后继结点引用(指针)
self.prev: ListNode | None = None # 前驱结点引用(指针)
class LinkedListDeque:
""" 基于双向链表实现的双向队列 """
def __init__(self) -> None:
""" 构造方法 """
self.front: Optional[ListNode] = None # 头结点 front
self.rear: Optional[ListNode] = None # 尾结点 rear
self.front: ListNode | None = None # 头结点 front
self.rear: ListNode | None = None # 尾结点 rear
self.__size: int = 0 # 双向队列的长度
def size(self) -> int:
@ -651,7 +651,7 @@ comments: true
if is_front:
val: int = self.front.val # 暂存头结点值
# 删除头结点
fnext: Optional[ListNode] = self.front.next
fnext: ListNode | None = self.front.next
if fnext != None:
fnext.prev = None
self.front.next = None
@ -660,7 +660,7 @@ comments: true
else:
val: int = self.rear.val # 暂存尾结点值
# 删除尾结点
rprev: Optional[ListNode] = self.rear.prev
rprev: ListNode | None = self.rear.prev
if rprev != None:
rprev.next = None
self.rear.prev = None
@ -684,10 +684,10 @@ comments: true
""" 访问队尾元素 """
return None if self.is_empty() else self.rear.val
def to_array(self) -> List[int]:
def to_array(self) -> list[int]:
""" 返回数组用于打印 """
node: Optional[ListNode] = self.front
res: List[int] = [0] * self.size()
node: ListNode | None = self.front
res: list[int] = [0] * self.size()
for i in range(self.size()):
res[i] = node.val
node = node.next
@ -1584,10 +1584,9 @@ comments: true
```python title="array_deque.py"
class ArrayDeque:
""" 基于环形数组实现的双向队列 """
def __init__(self, capacity: int) -> None:
""" 构造方法 """
self.__nums: List[int] = [0] * capacity
self.__nums: list[int] = [0] * capacity
self.__front: int = 0
self.__size: int = 0
@ -1659,7 +1658,7 @@ comments: true
last = self.index(self.__front + self.__size - 1)
return self.__nums[last]
def to_array(self) -> List[int]:
def to_array(self) -> list[int]:
""" 返回数组用于打印 """
# 仅转换有效长度范围内的列表元素
res = []

View file

@ -431,8 +431,8 @@ comments: true
""" 基于链表实现的队列 """
def __init__(self):
""" 构造方法 """
self.__front: Optional[ListNode] = None # 头结点 front
self.__rear: Optional[ListNode] = None # 尾结点 rear
self.__front: ListNode | None = None # 头结点 front
self.__rear: ListNode | None = None # 尾结点 rear
self.__size: int = 0
def size(self) -> int:
@ -472,7 +472,7 @@ comments: true
return False
return self.__front.val
def to_list(self) -> List[int]:
def to_list(self) -> list[int]:
""" 转化为列表用于打印 """
queue = []
temp = self.__front
@ -1106,7 +1106,7 @@ comments: true
""" 基于环形数组实现的队列 """
def __init__(self, size: int) -> None:
""" 构造方法 """
self.__nums: List[int] = [0] * size # 用于存储队列元素的数组
self.__nums: list[int] = [0] * size # 用于存储队列元素的数组
self.__front: int = 0 # 队首指针,指向队首元素
self.__size: int = 0 # 队列长度
@ -1145,9 +1145,9 @@ comments: true
assert not self.is_empty(), "队列为空"
return self.__nums[self.__front]
def to_list(self) -> List[int]:
def to_list(self) -> list[int]:
""" 返回列表用于打印 """
res: List[int] = [0] * self.size()
res: list[int] = [0] * self.size()
j: int = self.__front
for i in range(self.size()):
res[i] = self.__nums[(j % self.capacity())]

View file

@ -412,7 +412,7 @@ comments: true
""" 基于链表实现的栈 """
def __init__(self):
""" 构造方法 """
self.__peek: Optional[ListNode] = None
self.__peek: ListNode | None = None
self.__size: int = 0
def size(self) -> int:
@ -443,9 +443,9 @@ comments: true
if not self.__peek: return None
return self.__peek.val
def to_list(self) -> List[int]:
def to_list(self) -> list[int]:
""" 转化为列表用于打印 """
arr: List[int] = []
arr: list[int] = []
node = self.__peek
while node:
arr.append(node.val)
@ -954,7 +954,7 @@ comments: true
""" 基于数组实现的栈 """
def __init__(self) -> None:
""" 构造方法 """
self.__stack: List[int] = []
self.__stack: list[int] = []
def size(self) -> int:
""" 获取栈的长度 """
@ -978,7 +978,7 @@ comments: true
assert not self.is_empty(), "栈为空"
return self.__stack[-1]
def to_list(self) -> List[int]:
def to_list(self) -> list[int]:
""" 返回列表用于打印 """
return self.__stack
```

View file

@ -194,14 +194,14 @@ G. M. Adelson-Velsky 和 E. M. Landis 在其 1962 年发表的论文 "An algorit
=== "Python"
```python title="avl_tree.py"
def height(self, node: Optional[TreeNode]) -> int:
def height(self, node: TreeNode | None) -> int:
""" 获取结点高度 """
# 空结点高度为 -1 ,叶结点高度为 0
if node is not None:
return node.height
return -1
def __update_height(self, node: Optional[TreeNode]):
def __update_height(self, node: TreeNode | None):
""" 更新结点高度 """
# 结点高度等于最高子树高度 + 1
node.height = max([self.height(node.left), self.height(node.right)]) + 1
@ -354,7 +354,7 @@ G. M. Adelson-Velsky 和 E. M. Landis 在其 1962 年发表的论文 "An algorit
=== "Python"
```python title="avl_tree.py"
def balance_factor(self, node: Optional[TreeNode]) -> int:
def balance_factor(self, node: TreeNode | None) -> int:
""" 获取平衡因子 """
# 空结点平衡因子为 0
if node is None:
@ -517,7 +517,7 @@ AVL 树的独特之处在于「旋转 Rotation」的操作其可 **在不影
=== "Python"
```python title="avl_tree.py"
def __right_rotate(self, node: Optional[TreeNode]) -> Optional[TreeNode]:
def __right_rotate(self, node: TreeNode | None) -> TreeNode | None:
""" 右旋操作 """
child = node.left
grand_child = child.right
@ -701,7 +701,7 @@ AVL 树的独特之处在于「旋转 Rotation」的操作其可 **在不影
=== "Python"
```python title="avl_tree.py"
def __left_rotate(self, node: Optional[TreeNode]) -> Optional[TreeNode]:
def __left_rotate(self, node: TreeNode | None) -> TreeNode | None:
""" 左旋操作 """
child = node.right
grand_child = child.left
@ -940,7 +940,7 @@ AVL 树的独特之处在于「旋转 Rotation」的操作其可 **在不影
=== "Python"
```python title="avl_tree.py"
def __rotate(self, node: Optional[TreeNode]) -> Optional[TreeNode]:
def __rotate(self, node: TreeNode | None) -> TreeNode | None:
""" 执行旋转操作,使该子树重新恢复平衡 """
# 获取结点 node 的平衡因子
balance_factor = self.balance_factor(node)
@ -1255,7 +1255,7 @@ AVL 树的独特之处在于「旋转 Rotation」的操作其可 **在不影
self.__root = self.__insert_helper(self.__root, val)
return self.__root
def __insert_helper(self, node: Optional[TreeNode], val: int) -> TreeNode:
def __insert_helper(self, node: TreeNode | None, val: int) -> TreeNode:
""" 递归插入结点(辅助方法)"""
if node is None:
return TreeNode(val)
@ -1575,12 +1575,12 @@ AVL 树的独特之处在于「旋转 Rotation」的操作其可 **在不影
=== "Python"
```python title="avl_tree.py"
def remove(self, val: int) -> Optional[TreeNode]:
def remove(self, val: int) -> TreeNode | None:
""" 删除结点 """
self.__root = self.__remove_helper(self.__root, val)
return self.__root
def __remove_helper(self, node: Optional[TreeNode], val: int) -> Optional[TreeNode]:
def __remove_helper(self, node: TreeNode | None, val: int) -> TreeNode | None:
""" 递归删除结点(辅助方法) """
if node is None:
return None
@ -1607,7 +1607,7 @@ AVL 树的独特之处在于「旋转 Rotation」的操作其可 **在不影
# 2. 执行旋转操作,使该子树重新恢复平衡
return self.__rotate(node)
def __get_inorder_next(self, node: Optional[TreeNode]) -> Optional[TreeNode]:
def __get_inorder_next(self, node: TreeNode | None) -> TreeNode | None:
""" 获取中序遍历中的下一个结点(仅适用于 root 有左子结点的情况) """
if node is None:
return None

View file

@ -80,9 +80,9 @@ comments: true
=== "Python"
```python title="binary_search_tree.py"
def search(self, num: int) -> Optional[TreeNode]:
def search(self, num: int) -> TreeNode | None:
""" 查找结点 """
cur: Optional[TreeNode] = self.__root
cur: TreeNode | None = self.__root
# 循环查找,越过叶结点后跳出
while cur is not None:
# 目标结点在 cur 的右子树中
@ -308,7 +308,7 @@ comments: true
=== "Python"
```python title="binary_search_tree.py"
def insert(self, num: int) -> Optional[TreeNode]:
def insert(self, num: int) -> TreeNode | None:
""" 插入结点 """
# 若树为空,直接提前返回
if self.__root is None:
@ -691,7 +691,7 @@ comments: true
=== "Python"
```python title="binary_search_tree.py"
def remove(self, num: int) -> Optional[TreeNode]:
def remove(self, num: int) -> TreeNode | None:
""" 删除结点 """
# 若树为空,直接提前返回
if self.__root is None:
@ -732,7 +732,7 @@ comments: true
cur.val = tmp
return cur
def get_inorder_next(self, root: Optional[TreeNode]) -> Optional[TreeNode]:
def get_inorder_next(self, root: TreeNode | None) -> TreeNode | None:
""" 获取中序遍历中的下一个结点(仅适用于 root 有左子结点的情况) """
if root is None:
return root

View file

@ -69,13 +69,13 @@ comments: true
=== "Python"
```python title="binary_tree_bfs.py"
def level_order(root: Optional[TreeNode]) -> List[int]:
def level_order(root: TreeNode | None) -> list[int]:
""" 层序遍历 """
# 初始化队列,加入根结点
queue: Deque[TreeNode] = collections.deque()
queue: deque[TreeNode] = deque()
queue.append(root)
# 初始化一个列表,用于保存遍历序列
res: List[int] = []
res: list[int] = []
while queue:
node: TreeNode = queue.popleft() # 队列出队
res.append(node.val) # 保存结点值
@ -337,7 +337,7 @@ comments: true
=== "Python"
```python title="binary_tree_dfs.py"
def pre_order(root: Optional[TreeNode]) -> None:
def pre_order(root: TreeNode | None) -> None:
""" 前序遍历 """
if root is None:
return
@ -346,7 +346,7 @@ comments: true
pre_order(root=root.left)
pre_order(root=root.right)
def in_order(root: Optional[TreeNode]) -> None:
def in_order(root: TreeNode | None) -> None:
""" 中序遍历 """
if root is None:
return
@ -355,7 +355,7 @@ comments: true
res.append(root.val)
in_order(root=root.right)
def post_order(root: Optional[TreeNode]) -> None:
def post_order(root: TreeNode | None) -> None:
""" 后序遍历 """
if root is None:
return