mirror of
https://github.com/krahets/hello-algo.git
synced 2024-12-27 00:16:30 +08:00
build
This commit is contained in:
parent
2715ce703a
commit
0dfdcf0bab
25 changed files with 118 additions and 115 deletions
|
@ -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:
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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]
|
||||
```
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 = {}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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])
|
||||
|
|
|
@ -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
|
||||
```
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 地统计,有时可以采用一些常见分布来近似,例如自然界的正态分布;
|
||||
- 先粗略设置分界线,将元素分配完后,**把元素较多的桶继续划分为多个桶**,直至所有桶内元素数量合理为止;该做法本质上是一个递归树;
|
||||
- 如果我们提前知道商品价格的概率分布,**则可以根据已知分布来设置每个桶的价格分界线**;值得说明的是,数据分布不一定需要特意统计,也可以根据数据特点采用某种常见概率模型来近似,例如自然界的正态分布等;
|
||||
|
||||
(图)
|
||||
|
||||
另外,排序桶内元素需要选择一种合适的排序算法,比如快速排序。
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)):
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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 = []
|
||||
|
|
|
@ -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())]
|
||||
|
|
|
@ -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
|
||||
```
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue