build
This commit is contained in:
parent
01d05cc1f0
commit
37f11aff68
@ -150,7 +150,7 @@ elementAddr = firtstElementAddr + elementLength * elementIndex
|
||||
|
||||
```python title="array.py"
|
||||
def random_access(nums: list[int]) -> int:
|
||||
""" 随机访问元素 """
|
||||
"""随机访问元素"""
|
||||
# 在区间 [0, len(nums)-1] 中随机抽取一个数字
|
||||
random_index = random.randint(0, len(nums) - 1)
|
||||
# 获取并返回随机元素
|
||||
@ -286,7 +286,7 @@ elementAddr = firtstElementAddr + elementLength * elementIndex
|
||||
|
||||
```python title="array.py"
|
||||
def extend(nums: list[int], enlarge: int) -> list[int]:
|
||||
""" 扩展数组长度 """
|
||||
"""扩展数组长度"""
|
||||
# 初始化一个扩展长度后的数组
|
||||
res = [0] * (len(nums) + enlarge)
|
||||
# 将原数组中的所有元素复制到新数组
|
||||
@ -441,7 +441,7 @@ elementAddr = firtstElementAddr + elementLength * elementIndex
|
||||
|
||||
```python title="array.py"
|
||||
def insert(nums: list[int], num: int, index: int) -> None:
|
||||
""" 在数组的索引 index 处插入元素 num """
|
||||
"""在数组的索引 index 处插入元素 num"""
|
||||
# 把索引 index 以及之后的所有元素向后移动一位
|
||||
for i in range(len(nums) - 1, index, -1):
|
||||
nums[i] = nums[i - 1]
|
||||
@ -561,7 +561,7 @@ elementAddr = firtstElementAddr + elementLength * elementIndex
|
||||
|
||||
```python title="array.py"
|
||||
def remove(nums: list[int], index: int) -> None:
|
||||
""" 删除索引 index 处元素 """
|
||||
"""删除索引 index 处元素"""
|
||||
# 把索引 index 之后的所有元素向前移动一位
|
||||
for i in range(index, len(nums) - 1):
|
||||
nums[i] = nums[i + 1]
|
||||
@ -693,7 +693,7 @@ elementAddr = firtstElementAddr + elementLength * elementIndex
|
||||
|
||||
```python title="array.py"
|
||||
def traverse(nums: list[int]) -> None:
|
||||
""" 遍历数组 """
|
||||
"""遍历数组"""
|
||||
count = 0
|
||||
# 通过索引遍历数组
|
||||
for i in range(len(nums)):
|
||||
@ -849,7 +849,7 @@ elementAddr = firtstElementAddr + elementLength * elementIndex
|
||||
|
||||
```python title="array.py"
|
||||
def find(nums: list[int], target: int) -> int:
|
||||
""" 在数组中查找指定元素 """
|
||||
"""在数组中查找指定元素"""
|
||||
for i in range(len(nums)):
|
||||
if nums[i] == target:
|
||||
return i
|
||||
|
||||
@ -4,11 +4,11 @@ comments: true
|
||||
|
||||
# 4.2. 链表
|
||||
|
||||
内存空间是所有程序的公共资源,排除已被占用的内存空间,空闲内存空间通常散落在内存各处。在上一节中,我们提到存储数组的内存空间必须是连续的,而当我们需要申请一个非常大的数组时,空闲内存中可能没有这么大的连续空间。
|
||||
内存空间是所有程序的公共资源,排除已被占用的内存空间,空闲内存空间通常散落在内存各处。在上一节中,我们提到存储数组的内存空间必须是连续的,而当我们需要申请一个非常大的数组时,空闲内存中可能没有这么大的连续空间。与数组相比,链表更具灵活性,它可以被存储在非连续的内存空间中。
|
||||
|
||||
与数组相比,链表更具灵活性,因为它可以存储在非连续的内存空间。「链表 Linked List」是一种线性数据结构,其每个元素都是一个节点对象,各个节点之间通过指针连接,从当前节点通过指针可以访问到下一个节点。由于指针记录了下个节点的内存地址,因此无需保证内存地址的连续性,从而可以将各个节点分散存储在内存各处。
|
||||
「链表 Linked List」是一种线性数据结构,其每个元素都是一个节点对象,各个节点之间通过指针连接,从当前节点通过指针可以访问到下一个节点。**由于指针记录了下个节点的内存地址,因此无需保证内存地址的连续性**,从而可以将各个节点分散存储在内存各处。
|
||||
|
||||
链表「节点 Node」包含两项数据,一是节点「值 Value」,二是指向下一节点的「指针 Pointer」,或称指向下一节点的「引用 Reference」。
|
||||
链表「节点 Node」包含两项数据,一是节点「值 Value」,二是指向下一节点的「指针 Pointer」,或称「引用 Reference」。
|
||||
|
||||

|
||||
|
||||
@ -374,7 +374,7 @@ comments: true
|
||||
|
||||
```python title="linked_list.py"
|
||||
def insert(n0: ListNode, P: ListNode) -> None:
|
||||
""" 在链表的节点 n0 之后插入节点 P """
|
||||
"""在链表的节点 n0 之后插入节点 P"""
|
||||
n1 = n0.next
|
||||
P.next = n1
|
||||
n0.next = P
|
||||
@ -493,7 +493,7 @@ comments: true
|
||||
|
||||
```python title="linked_list.py"
|
||||
def remove(n0: ListNode) -> None:
|
||||
""" 删除链表的节点 n0 之后的首个节点 """
|
||||
"""删除链表的节点 n0 之后的首个节点"""
|
||||
if not n0.next:
|
||||
return
|
||||
# n0 -> P -> n1
|
||||
@ -632,7 +632,7 @@ comments: true
|
||||
|
||||
```python title="linked_list.py"
|
||||
def access(head: ListNode, index: int) -> ListNode | None:
|
||||
""" 访问链表中索引为 index 的节点 """
|
||||
"""访问链表中索引为 index 的节点"""
|
||||
for _ in range(index):
|
||||
if not head:
|
||||
return None
|
||||
@ -780,7 +780,7 @@ comments: true
|
||||
|
||||
```python title="linked_list.py"
|
||||
def find(head: ListNode, target: int) -> int:
|
||||
""" 在链表中查找值为 target 的首个节点 """
|
||||
"""在链表中查找值为 target 的首个节点"""
|
||||
index = 0
|
||||
while head:
|
||||
if head.val == target:
|
||||
|
||||
@ -934,35 +934,36 @@ comments: true
|
||||
|
||||
```python title="my_list.py"
|
||||
class MyList:
|
||||
""" 列表类简易实现 """
|
||||
"""列表类简易实现"""
|
||||
|
||||
def __init__(self):
|
||||
""" 构造方法 """
|
||||
self.__capacity: int = 10 # 列表容量
|
||||
"""构造方法"""
|
||||
self.__capacity: int = 10 # 列表容量
|
||||
self.__nums: my_list[int] = [0] * self.__capacity # 数组(存储列表元素)
|
||||
self.__size: int = 0 # 列表长度(即当前元素数量)
|
||||
self.__extend_ratio: int = 2 # 每次列表扩容的倍数
|
||||
self.__size: int = 0 # 列表长度(即当前元素数量)
|
||||
self.__extend_ratio: int = 2 # 每次列表扩容的倍数
|
||||
|
||||
def size(self) -> int:
|
||||
""" 获取列表长度(即当前元素数量) """
|
||||
"""获取列表长度(即当前元素数量)"""
|
||||
return self.__size
|
||||
|
||||
|
||||
def capacity(self) -> int:
|
||||
""" 获取列表容量 """
|
||||
"""获取列表容量"""
|
||||
return self.__capacity
|
||||
|
||||
|
||||
def get(self, index: int) -> int:
|
||||
""" 访问元素 """
|
||||
"""访问元素"""
|
||||
# 索引如果越界则抛出异常,下同
|
||||
assert index >= 0 and index < self.__size, "索引越界"
|
||||
return self.__nums[index]
|
||||
|
||||
def set(self, num: int, index: int) -> None:
|
||||
""" 更新元素 """
|
||||
"""更新元素"""
|
||||
assert index >= 0 and index < self.__size, "索引越界"
|
||||
self.__nums[index] = num
|
||||
|
||||
|
||||
def add(self, num: int) -> None:
|
||||
""" 尾部添加元素 """
|
||||
"""尾部添加元素"""
|
||||
# 元素数量超出容量时,触发扩容机制
|
||||
if self.size() == self.capacity():
|
||||
self.extend_capacity()
|
||||
@ -970,7 +971,7 @@ comments: true
|
||||
self.__size += 1
|
||||
|
||||
def insert(self, num: int, index: int) -> None:
|
||||
""" 中间插入元素 """
|
||||
"""中间插入元素"""
|
||||
assert index >= 0 and index < self.__size, "索引越界"
|
||||
# 元素数量超出容量时,触发扩容机制
|
||||
if self.__size == self.capacity():
|
||||
@ -983,7 +984,7 @@ comments: true
|
||||
self.__size += 1
|
||||
|
||||
def remove(self, index: int) -> int:
|
||||
""" 删除元素 """
|
||||
"""删除元素"""
|
||||
assert index >= 0 and index < self.__size, "索引越界"
|
||||
num = self.__nums[index]
|
||||
# 索引 i 之后的元素都向前移动一位
|
||||
@ -995,15 +996,15 @@ comments: true
|
||||
return num
|
||||
|
||||
def extend_capacity(self) -> None:
|
||||
""" 列表扩容 """
|
||||
"""列表扩容"""
|
||||
# 新建一个长度为 self.__size 的数组,并将原数组拷贝到新数组
|
||||
self.__nums = self.__nums + [0] * self.capacity() * (self.__extend_ratio - 1)
|
||||
# 更新列表容量
|
||||
self.__capacity = len(self.__nums)
|
||||
|
||||
|
||||
def to_array(self) -> list[int]:
|
||||
""" 返回有效长度的列表 """
|
||||
return self.__nums[:self.__size]
|
||||
"""返回有效长度的列表"""
|
||||
return self.__nums[: self.__size]
|
||||
```
|
||||
|
||||
=== "Go"
|
||||
|
||||
@ -626,7 +626,7 @@ $$
|
||||
|
||||
```python title="space_complexity.py"
|
||||
def constant(n: int) -> None:
|
||||
""" 常数阶 """
|
||||
"""常数阶"""
|
||||
# 常量、变量、对象占用 O(1) 空间
|
||||
a: int = 0
|
||||
nums: list[int] = [0] * 10000
|
||||
@ -831,7 +831,7 @@ $$
|
||||
|
||||
```python title="space_complexity.py"
|
||||
def linear(n: int) -> None:
|
||||
""" 线性阶 """
|
||||
"""线性阶"""
|
||||
# 长度为 n 的列表占用 O(n) 空间
|
||||
nums: list[int] = [0] * n
|
||||
# 长度为 n 的哈希表占用 O(n) 空间
|
||||
@ -998,9 +998,10 @@ $$
|
||||
|
||||
```python title="space_complexity.py"
|
||||
def linear_recur(n: int) -> None:
|
||||
""" 线性阶(递归实现) """
|
||||
"""线性阶(递归实现)"""
|
||||
print("递归 n =", n)
|
||||
if n == 1: return
|
||||
if n == 1:
|
||||
return
|
||||
linear_recur(n - 1)
|
||||
```
|
||||
|
||||
@ -1129,7 +1130,7 @@ $$
|
||||
|
||||
```python title="space_complexity.py"
|
||||
def quadratic(n: int) -> None:
|
||||
""" 平方阶 """
|
||||
"""平方阶"""
|
||||
# 二维列表占用 O(n^2) 空间
|
||||
num_matrix: list[list[int]] = [[0] * n for _ in range(n)]
|
||||
```
|
||||
@ -1277,8 +1278,9 @@ $$
|
||||
|
||||
```python title="space_complexity.py"
|
||||
def quadratic_recur(n: int) -> int:
|
||||
""" 平方阶(递归实现) """
|
||||
if n <= 0: return 0
|
||||
"""平方阶(递归实现)"""
|
||||
if n <= 0:
|
||||
return 0
|
||||
# 数组 nums 长度为 n, n-1, ..., 2, 1
|
||||
nums: list[int] = [0] * n
|
||||
return quadratic_recur(n - 1)
|
||||
@ -1407,8 +1409,9 @@ $$
|
||||
|
||||
```python title="space_complexity.py"
|
||||
def build_tree(n: int) -> TreeNode | None:
|
||||
""" 指数阶(建立满二叉树) """
|
||||
if n == 0: return None
|
||||
"""指数阶(建立满二叉树)"""
|
||||
if n == 0:
|
||||
return None
|
||||
root = TreeNode(0)
|
||||
root.left = build_tree(n - 1)
|
||||
root.right = build_tree(n - 1)
|
||||
|
||||
@ -66,7 +66,7 @@ comments: true
|
||||
|
||||
```python title="leetcode_two_sum.py"
|
||||
def two_sum_brute_force(nums: list[int], target: int) -> list[int]:
|
||||
""" 方法一:暴力枚举 """
|
||||
"""方法一:暴力枚举"""
|
||||
# 两层循环,时间复杂度 O(n^2)
|
||||
for i in range(len(nums) - 1):
|
||||
for j in range(i + 1, len(nums)):
|
||||
@ -243,7 +243,7 @@ comments: true
|
||||
|
||||
```python title="leetcode_two_sum.py"
|
||||
def two_sum_hash_table(nums: list[int], target: int) -> list[int]:
|
||||
""" 方法二:辅助哈希表 """
|
||||
"""方法二:辅助哈希表"""
|
||||
# 辅助哈希表,空间复杂度 O(n)
|
||||
dic = {}
|
||||
# 单层循环,时间复杂度 O(n)
|
||||
|
||||
@ -820,7 +820,7 @@ $$
|
||||
|
||||
```python title="time_complexity.py"
|
||||
def constant(n: int) -> int:
|
||||
""" 常数阶 """
|
||||
"""常数阶"""
|
||||
count: int = 0
|
||||
size: int = 100000
|
||||
for _ in range(size):
|
||||
@ -948,7 +948,7 @@ $$
|
||||
|
||||
```python title="time_complexity.py"
|
||||
def linear(n: int) -> int:
|
||||
""" 线性阶 """
|
||||
"""线性阶"""
|
||||
count: int = 0
|
||||
for _ in range(n):
|
||||
count += 1
|
||||
@ -1074,7 +1074,7 @@ $$
|
||||
|
||||
```python title="time_complexity.py"
|
||||
def array_traversal(nums: list[int]) -> int:
|
||||
""" 线性阶(遍历数组)"""
|
||||
"""线性阶(遍历数组)"""
|
||||
count: int = 0
|
||||
# 循环次数与数组长度成正比
|
||||
for num in nums:
|
||||
@ -1214,7 +1214,7 @@ $$
|
||||
|
||||
```python title="time_complexity.py"
|
||||
def quadratic(n: int) -> int:
|
||||
""" 平方阶 """
|
||||
"""平方阶"""
|
||||
count: int = 0
|
||||
# 循环次数与数组长度成平方关系
|
||||
for i in range(n):
|
||||
@ -1390,7 +1390,7 @@ $$
|
||||
|
||||
```python title="time_complexity.py"
|
||||
def bubble_sort(nums: list[int]) -> int:
|
||||
""" 平方阶(冒泡排序)"""
|
||||
"""平方阶(冒泡排序)"""
|
||||
count: int = 0 # 计数器
|
||||
# 外循环:待排序元素数量为 n-1, n-2, ..., 1
|
||||
for i in range(len(nums) - 1, 0, -1):
|
||||
@ -1603,7 +1603,7 @@ $$
|
||||
|
||||
```python title="time_complexity.py"
|
||||
def exponential(n: int) -> int:
|
||||
""" 指数阶(循环实现)"""
|
||||
"""指数阶(循环实现)"""
|
||||
count: int = 0
|
||||
base: int = 1
|
||||
# cell 每轮一分为二,形成数列 1, 2, 4, 8, ..., 2^(n-1)
|
||||
@ -1768,8 +1768,9 @@ $$
|
||||
|
||||
```python title="time_complexity.py"
|
||||
def exp_recur(n: int) -> int:
|
||||
""" 指数阶(递归实现)"""
|
||||
if n == 1: return 1
|
||||
"""指数阶(递归实现)"""
|
||||
if n == 1:
|
||||
return 1
|
||||
return exp_recur(n - 1) + exp_recur(n - 1) + 1
|
||||
```
|
||||
|
||||
@ -1884,7 +1885,7 @@ $$
|
||||
|
||||
```python title="time_complexity.py"
|
||||
def logarithmic(n: float) -> int:
|
||||
""" 对数阶(循环实现)"""
|
||||
"""对数阶(循环实现)"""
|
||||
count: int = 0
|
||||
while n > 1:
|
||||
n = n / 2
|
||||
@ -2017,8 +2018,9 @@ $$
|
||||
|
||||
```python title="time_complexity.py"
|
||||
def log_recur(n: float) -> int:
|
||||
""" 对数阶(递归实现)"""
|
||||
if n <= 1: return 0
|
||||
"""对数阶(递归实现)"""
|
||||
if n <= 1:
|
||||
return 0
|
||||
return log_recur(n / 2) + 1
|
||||
```
|
||||
|
||||
@ -2133,10 +2135,10 @@ $$
|
||||
|
||||
```python title="time_complexity.py"
|
||||
def linear_log_recur(n: float) -> int:
|
||||
""" 线性对数阶 """
|
||||
if n <= 1: return 1
|
||||
count: int = linear_log_recur(n // 2) + \
|
||||
linear_log_recur(n // 2)
|
||||
"""线性对数阶"""
|
||||
if n <= 1:
|
||||
return 1
|
||||
count: int = linear_log_recur(n // 2) + linear_log_recur(n // 2)
|
||||
for _ in range(n):
|
||||
count += 1
|
||||
return count
|
||||
@ -2290,8 +2292,9 @@ $$
|
||||
|
||||
```python title="time_complexity.py"
|
||||
def factorial_recur(n: int) -> int:
|
||||
""" 阶乘阶(递归实现)"""
|
||||
if n == 0: return 1
|
||||
"""阶乘阶(递归实现)"""
|
||||
if n == 0:
|
||||
return 1
|
||||
count: int = 0
|
||||
# 从 1 个分裂出 n 个
|
||||
for _ in range(n):
|
||||
@ -2480,7 +2483,7 @@ $$
|
||||
|
||||
```python title="worst_best_time_complexity.py"
|
||||
def random_numbers(n: int) -> list[int]:
|
||||
""" 生成一个数组,元素为: 1, 2, ..., n ,顺序被打乱 """
|
||||
"""生成一个数组,元素为: 1, 2, ..., n ,顺序被打乱"""
|
||||
# 生成数组 nums =: 1, 2, 3, ..., n
|
||||
nums: list[int] = [i for i in range(1, n + 1)]
|
||||
# 随机打乱数组元素
|
||||
@ -2488,7 +2491,7 @@ $$
|
||||
return nums
|
||||
|
||||
def find_one(nums: list[int]) -> int:
|
||||
""" 查找数组 nums 中数字 1 所在索引 """
|
||||
"""查找数组 nums 中数字 1 所在索引"""
|
||||
for i in range(len(nums)):
|
||||
# 当元素 1 在数组头部时,达到最佳时间复杂度 O(1)
|
||||
# 当元素 1 在数组尾部时,达到最差时间复杂度 O(n)
|
||||
|
||||
@ -214,14 +214,15 @@ comments: true
|
||||
|
||||
```python title="graph_adjacency_matrix.py"
|
||||
class GraphAdjMat:
|
||||
""" 基于邻接矩阵实现的无向图类 """
|
||||
"""基于邻接矩阵实现的无向图类"""
|
||||
|
||||
# 顶点列表,元素代表“顶点值”,索引代表“顶点索引”
|
||||
vertices: list[int] = []
|
||||
# 邻接矩阵,行列索引对应“顶点索引”
|
||||
adj_mat: list[list[int]] = []
|
||||
|
||||
def __init__(self, vertices: list[int], edges: list[list[int]]) -> None:
|
||||
""" 构造方法 """
|
||||
"""构造方法"""
|
||||
self.vertices: list[int] = []
|
||||
self.adj_mat: list[list[int]] = []
|
||||
# 添加顶点
|
||||
@ -233,11 +234,11 @@ comments: true
|
||||
self.add_edge(e[0], e[1])
|
||||
|
||||
def size(self) -> int:
|
||||
""" 获取顶点数量 """
|
||||
"""获取顶点数量"""
|
||||
return len(self.vertices)
|
||||
|
||||
def add_vertex(self, val: int) -> None:
|
||||
""" 添加顶点 """
|
||||
"""添加顶点"""
|
||||
n = self.size()
|
||||
# 向顶点列表中添加新顶点的值
|
||||
self.vertices.append(val)
|
||||
@ -249,7 +250,7 @@ comments: true
|
||||
row.append(0)
|
||||
|
||||
def remove_vertex(self, index: int) -> None:
|
||||
""" 删除顶点 """
|
||||
"""删除顶点"""
|
||||
if index >= self.size():
|
||||
raise IndexError()
|
||||
# 在顶点列表中移除索引 index 的顶点
|
||||
@ -261,7 +262,7 @@ comments: true
|
||||
row.pop(index)
|
||||
|
||||
def add_edge(self, i: int, j: int) -> None:
|
||||
""" 添加边 """
|
||||
"""添加边"""
|
||||
# 参数 i, j 对应 vertices 元素索引
|
||||
# 索引越界与相等处理
|
||||
if i < 0 or j < 0 or i >= self.size() or j >= self.size() or i == j:
|
||||
@ -271,7 +272,7 @@ comments: true
|
||||
self.adj_mat[j][i] = 1
|
||||
|
||||
def remove_edge(self, i: int, j: int) -> None:
|
||||
""" 删除边 """
|
||||
"""删除边"""
|
||||
# 参数 i, j 对应 vertices 元素索引
|
||||
# 索引越界与相等处理
|
||||
if i < 0 or j < 0 or i >= self.size() or j >= self.size() or i == j:
|
||||
@ -280,7 +281,7 @@ comments: true
|
||||
self.adj_mat[j][i] = 0
|
||||
|
||||
def print(self) -> None:
|
||||
""" 打印邻接矩阵 """
|
||||
"""打印邻接矩阵"""
|
||||
print("顶点列表 =", self.vertices)
|
||||
print("邻接矩阵 =")
|
||||
print_matrix(self.adj_mat)
|
||||
@ -966,9 +967,10 @@ comments: true
|
||||
|
||||
```python title="graph_adjacency_list.py"
|
||||
class GraphAdjList:
|
||||
""" 基于邻接表实现的无向图类 """
|
||||
"""基于邻接表实现的无向图类"""
|
||||
|
||||
def __init__(self, edges: list[list[Vertex]]) -> None:
|
||||
""" 构造方法 """
|
||||
"""构造方法"""
|
||||
# 邻接表,key: 顶点,value:该顶点的所有邻接顶点
|
||||
self.adj_list = dict[Vertex, Vertex]()
|
||||
# 添加所有顶点和边
|
||||
@ -978,11 +980,11 @@ comments: true
|
||||
self.add_edge(edge[0], edge[1])
|
||||
|
||||
def size(self) -> int:
|
||||
""" 获取顶点数量 """
|
||||
"""获取顶点数量"""
|
||||
return len(self.adj_list)
|
||||
|
||||
def add_edge(self, vet1: Vertex, vet2: Vertex) -> None:
|
||||
""" 添加边 """
|
||||
"""添加边"""
|
||||
if vet1 not in self.adj_list or vet2 not in self.adj_list or vet1 == vet2:
|
||||
raise ValueError
|
||||
# 添加边 vet1 - vet2
|
||||
@ -990,7 +992,7 @@ comments: true
|
||||
self.adj_list[vet2].append(vet1)
|
||||
|
||||
def remove_edge(self, vet1: Vertex, vet2: Vertex) -> None:
|
||||
""" 删除边 """
|
||||
"""删除边"""
|
||||
if vet1 not in self.adj_list or vet2 not in self.adj_list or vet1 == vet2:
|
||||
raise ValueError
|
||||
# 删除边 vet1 - vet2
|
||||
@ -998,14 +1000,14 @@ comments: true
|
||||
self.adj_list[vet2].remove(vet1)
|
||||
|
||||
def add_vertex(self, vet: Vertex) -> None:
|
||||
""" 添加顶点 """
|
||||
"""添加顶点"""
|
||||
if vet in self.adj_list:
|
||||
return
|
||||
# 在邻接表中添加一个新链表
|
||||
self.adj_list[vet] = []
|
||||
|
||||
def remove_vertex(self, vet: Vertex) -> None:
|
||||
""" 删除顶点 """
|
||||
"""删除顶点"""
|
||||
if vet not in self.adj_list:
|
||||
raise ValueError
|
||||
# 在邻接表中删除顶点 vet 对应的链表
|
||||
@ -1016,7 +1018,7 @@ comments: true
|
||||
self.adj_list[vertex].remove(vet)
|
||||
|
||||
def print(self) -> None:
|
||||
""" 打印邻接表 """
|
||||
"""打印邻接表"""
|
||||
print("邻接表 =")
|
||||
for vertex in self.adj_list:
|
||||
tmp = [v.val for v in self.adj_list[vertex]]
|
||||
|
||||
@ -94,7 +94,7 @@ BFS 通常借助「队列」来实现。队列具有“先入先出”的性质
|
||||
|
||||
```python title="graph_bfs.py"
|
||||
def graph_bfs(graph: GraphAdjList, start_vet: Vertex) -> list[Vertex]:
|
||||
""" 广度优先遍历 BFS """
|
||||
"""广度优先遍历 BFS"""
|
||||
# 使用邻接表来表示图,以便获取指定顶点的所有邻接顶点
|
||||
# 顶点遍历序列
|
||||
res = []
|
||||
@ -105,13 +105,13 @@ BFS 通常借助「队列」来实现。队列具有“先入先出”的性质
|
||||
# 以顶点 vet 为起点,循环直至访问完所有顶点
|
||||
while len(que) > 0:
|
||||
vet = que.popleft() # 队首顶点出队
|
||||
res.append(vet) # 记录访问顶点
|
||||
res.append(vet) # 记录访问顶点
|
||||
# 遍历该顶点的所有邻接顶点
|
||||
for adj_vet in graph.adj_list[vet]:
|
||||
if adj_vet in visited:
|
||||
continue # 跳过已被访问过的顶点
|
||||
continue # 跳过已被访问过的顶点
|
||||
que.append(adj_vet) # 只入队未访问的顶点
|
||||
visited.add(adj_vet) # 标记该顶点已被访问
|
||||
visited.add(adj_vet) # 标记该顶点已被访问
|
||||
# 返回顶点遍历序列
|
||||
return res
|
||||
```
|
||||
@ -379,18 +379,18 @@ BFS 通常借助「队列」来实现。队列具有“先入先出”的性质
|
||||
|
||||
```python title="graph_dfs.py"
|
||||
def dfs(graph: GraphAdjList, visited: set[Vertex], res: list[Vertex], vet: Vertex):
|
||||
""" 深度优先遍历 DFS 辅助函数 """
|
||||
res.append(vet) # 记录访问顶点
|
||||
visited.add(vet) # 标记该顶点已被访问
|
||||
"""深度优先遍历 DFS 辅助函数"""
|
||||
res.append(vet) # 记录访问顶点
|
||||
visited.add(vet) # 标记该顶点已被访问
|
||||
# 遍历该顶点的所有邻接顶点
|
||||
for adjVet in graph.adj_list[vet]:
|
||||
if adjVet in visited:
|
||||
continue # 跳过已被访问过的顶点
|
||||
continue # 跳过已被访问过的顶点
|
||||
# 递归访问邻接顶点
|
||||
dfs(graph, visited, res, adjVet)
|
||||
|
||||
def graph_dfs(graph: GraphAdjList, start_vet: Vertex) -> list[Vertex]:
|
||||
""" 深度优先遍历 DFS """
|
||||
"""深度优先遍历 DFS"""
|
||||
# 顶点遍历序列
|
||||
res = []
|
||||
# 哈希表,用于记录已被访问过的顶点
|
||||
|
||||
@ -607,25 +607,27 @@ $$
|
||||
|
||||
```python title="array_hash_map.py"
|
||||
class Entry:
|
||||
""" 键值对 int->String """
|
||||
"""键值对 int->String"""
|
||||
|
||||
def __init__(self, key: int, val: str):
|
||||
self.key = key
|
||||
self.val = val
|
||||
|
||||
class ArrayHashMap:
|
||||
""" 基于数组简易实现的哈希表 """
|
||||
"""基于数组简易实现的哈希表"""
|
||||
|
||||
def __init__(self):
|
||||
""" 构造方法 """
|
||||
"""构造方法"""
|
||||
# 初始化数组,包含 100 个桶
|
||||
self.buckets: list[Entry | None] = [None] * 100
|
||||
|
||||
def hash_func(self, key: int) -> int:
|
||||
""" 哈希函数 """
|
||||
"""哈希函数"""
|
||||
index: int = key % 100
|
||||
return index
|
||||
|
||||
def get(self, key: int) -> str:
|
||||
""" 查询操作 """
|
||||
"""查询操作"""
|
||||
index: int = self.hash_func(key)
|
||||
pair: Entry = self.buckets[index]
|
||||
if pair is None:
|
||||
@ -633,19 +635,19 @@ $$
|
||||
return pair.val
|
||||
|
||||
def put(self, key: int, val: str) -> None:
|
||||
""" 添加操作 """
|
||||
"""添加操作"""
|
||||
pair = Entry(key, val)
|
||||
index: int = self.hash_func(key)
|
||||
self.buckets[index] = pair
|
||||
|
||||
def remove(self, key: int) -> None:
|
||||
""" 删除操作 """
|
||||
"""删除操作"""
|
||||
index: int = self.hash_func(key)
|
||||
# 置为 None ,代表删除
|
||||
self.buckets[index] = None
|
||||
|
||||
def entry_set(self) -> list[Entry]:
|
||||
""" 获取所有键值对 """
|
||||
"""获取所有键值对"""
|
||||
result: list[Entry] = []
|
||||
for pair in self.buckets:
|
||||
if pair is not None:
|
||||
@ -653,7 +655,7 @@ $$
|
||||
return result
|
||||
|
||||
def key_set(self) -> list[int]:
|
||||
""" 获取所有键 """
|
||||
"""获取所有键"""
|
||||
result: list[int] = []
|
||||
for pair in self.buckets:
|
||||
if pair is not None:
|
||||
@ -661,7 +663,7 @@ $$
|
||||
return result
|
||||
|
||||
def value_set(self) -> list[str]:
|
||||
""" 获取所有值 """
|
||||
"""获取所有值"""
|
||||
result: list[str] = []
|
||||
for pair in self.buckets:
|
||||
if pair is not None:
|
||||
@ -669,7 +671,7 @@ $$
|
||||
return result
|
||||
|
||||
def print(self) -> None:
|
||||
""" 打印哈希表 """
|
||||
"""打印哈希表"""
|
||||
for pair in self.buckets:
|
||||
if pair is not None:
|
||||
print(pair.key, "->", pair.val)
|
||||
|
||||
@ -50,7 +50,7 @@ comments: true
|
||||
|
||||
```python title="my_heap.py"
|
||||
def __init__(self, nums: list[int]):
|
||||
""" 构造方法 """
|
||||
"""构造方法"""
|
||||
# 将列表元素原封不动添加进堆
|
||||
self.max_heap = nums
|
||||
# 堆化除叶节点以外的其他所有节点
|
||||
|
||||
@ -366,15 +366,15 @@ comments: true
|
||||
|
||||
```python title="my_heap.py"
|
||||
def left(self, i: int) -> int:
|
||||
""" 获取左子节点索引 """
|
||||
"""获取左子节点索引"""
|
||||
return 2 * i + 1
|
||||
|
||||
def right(self, i: int) -> int:
|
||||
""" 获取右子节点索引 """
|
||||
"""获取右子节点索引"""
|
||||
return 2 * i + 2
|
||||
|
||||
def parent(self, i: int) -> int:
|
||||
""" 获取父节点索引 """
|
||||
"""获取父节点索引"""
|
||||
return (i - 1) // 2 # 向下整除
|
||||
```
|
||||
|
||||
@ -533,7 +533,7 @@ comments: true
|
||||
|
||||
```python title="my_heap.py"
|
||||
def peek(self) -> int:
|
||||
""" 访问堆顶元素 """
|
||||
"""访问堆顶元素"""
|
||||
return self.max_heap[0]
|
||||
```
|
||||
|
||||
@ -682,14 +682,14 @@ comments: true
|
||||
|
||||
```python title="my_heap.py"
|
||||
def push(self, val: int):
|
||||
""" 元素入堆 """
|
||||
"""元素入堆"""
|
||||
# 添加节点
|
||||
self.max_heap.append(val)
|
||||
# 从底至顶堆化
|
||||
self.sift_up(self.size() - 1)
|
||||
|
||||
def sift_up(self, i: int):
|
||||
""" 从节点 i 开始,从底至顶堆化 """
|
||||
"""从节点 i 开始,从底至顶堆化"""
|
||||
while True:
|
||||
# 获取节点 i 的父节点
|
||||
p = self.parent(i)
|
||||
@ -996,7 +996,7 @@ comments: true
|
||||
|
||||
```python title="my_heap.py"
|
||||
def pop(self) -> int:
|
||||
""" 元素出堆 """
|
||||
"""元素出堆"""
|
||||
# 判空处理
|
||||
assert not self.is_empty()
|
||||
# 交换根节点与最右叶节点(即交换首元素与尾元素)
|
||||
@ -1009,7 +1009,7 @@ comments: true
|
||||
return val
|
||||
|
||||
def sift_down(self, i: int):
|
||||
""" 从节点 i 开始,从顶至底堆化 """
|
||||
"""从节点 i 开始,从顶至底堆化"""
|
||||
while True:
|
||||
# 判断节点 i, l, r 中值最大的节点,记为 ma
|
||||
l, r, ma = self.left(i), self.right(i), i
|
||||
|
||||
@ -99,18 +99,18 @@ $$
|
||||
|
||||
```python title="binary_search.py"
|
||||
def binary_search(nums: list[int], target: int) -> int:
|
||||
""" 二分查找(双闭区间) """
|
||||
"""二分查找(双闭区间)"""
|
||||
# 初始化双闭区间 [0, n-1] ,即 i, j 分别指向数组首元素、尾元素
|
||||
i, j = 0, len(nums) - 1
|
||||
while i <= j:
|
||||
m = (i + j) // 2 # 计算中点索引 m
|
||||
if nums[m] < target: # 此情况说明 target 在区间 [m+1, j] 中
|
||||
m = (i + j) // 2 # 计算中点索引 m
|
||||
if nums[m] < target: # 此情况说明 target 在区间 [m+1, j] 中
|
||||
i = m + 1
|
||||
elif nums[m] > target: # 此情况说明 target 在区间 [i, m-1] 中
|
||||
j = m - 1
|
||||
else:
|
||||
return m # 找到目标元素,返回其索引
|
||||
return -1 # 未找到目标元素,返回 -1
|
||||
return m # 找到目标元素,返回其索引
|
||||
return -1 # 未找到目标元素,返回 -1
|
||||
```
|
||||
|
||||
=== "Go"
|
||||
@ -310,19 +310,19 @@ $$
|
||||
|
||||
```python title="binary_search.py"
|
||||
def binary_search1(nums: list[int], target: int) -> int:
|
||||
""" 二分查找(左闭右开) """
|
||||
"""二分查找(左闭右开)"""
|
||||
# 初始化左闭右开 [0, n) ,即 i, j 分别指向数组首元素、尾元素+1
|
||||
i, j = 0, len(nums)
|
||||
# 循环,当搜索区间为空时跳出(当 i = j 时为空)
|
||||
while i < j:
|
||||
m = (i + j) // 2 # 计算中点索引 m
|
||||
if nums[m] < target: # 此情况说明 target 在区间 [m+1, j) 中
|
||||
m = (i + j) // 2 # 计算中点索引 m
|
||||
if nums[m] < target: # 此情况说明 target 在区间 [m+1, j) 中
|
||||
i = m + 1
|
||||
elif nums[m] > target: # 此情况说明 target 在区间 [i, m) 中
|
||||
j = m
|
||||
else: # 找到目标元素,返回其索引
|
||||
else: # 找到目标元素,返回其索引
|
||||
return m
|
||||
return -1 # 未找到目标元素,返回 -1
|
||||
return -1 # 未找到目标元素,返回 -1
|
||||
```
|
||||
|
||||
=== "Go"
|
||||
|
||||
@ -46,7 +46,7 @@ comments: true
|
||||
|
||||
```python title="hashing_search.py"
|
||||
def hashing_search_array(mapp: dict[int, int], target: int) -> int:
|
||||
""" 哈希查找(数组) """
|
||||
"""哈希查找(数组)"""
|
||||
# 哈希表的 key: 目标元素,value: 索引
|
||||
# 若哈希表中无此 key ,返回 -1
|
||||
return mapp.get(target, -1)
|
||||
@ -163,11 +163,8 @@ comments: true
|
||||
=== "Python"
|
||||
|
||||
```python title="hashing_search.py"
|
||||
def hashing_search_linkedlist(mapp: dict[int, ListNode], target: int) -> ListNode | None:
|
||||
""" 哈希查找(链表) """
|
||||
# 哈希表的 key: 目标元素,value: 节点对象
|
||||
# 若哈希表中无此 key ,返回 None
|
||||
return mapp.get(target, None)
|
||||
def hashing_search_linkedlist(
|
||||
mapp: dict[int, ListNode], target: int
|
||||
```
|
||||
|
||||
=== "Go"
|
||||
|
||||
@ -50,12 +50,12 @@ comments: true
|
||||
|
||||
```python title="linear_search.py"
|
||||
def linear_search_array(nums: list[int], target: int) -> int:
|
||||
""" 线性查找(数组) """
|
||||
"""线性查找(数组)"""
|
||||
# 遍历数组
|
||||
for i in range(len(nums)):
|
||||
if nums[i] == target: # 找到目标元素,返回其索引
|
||||
return i
|
||||
return -1 # 未找到目标元素,返回 -1
|
||||
return -1 # 未找到目标元素,返回 -1
|
||||
```
|
||||
|
||||
=== "Go"
|
||||
@ -207,13 +207,13 @@ comments: true
|
||||
|
||||
```python title="linear_search.py"
|
||||
def linear_search_linkedlist(head: ListNode, target: int) -> ListNode | None:
|
||||
""" 线性查找(链表) """
|
||||
"""线性查找(链表)"""
|
||||
# 遍历链表
|
||||
while head:
|
||||
if head.val == target: # 找到目标节点,返回之
|
||||
if head.val == target: # 找到目标节点,返回之
|
||||
return head
|
||||
head = head.next
|
||||
return None # 未找到目标节点,返回 None
|
||||
return None # 未找到目标节点,返回 None
|
||||
```
|
||||
|
||||
=== "Go"
|
||||
|
||||
@ -90,7 +90,7 @@ comments: true
|
||||
|
||||
```python title="bubble_sort.py"
|
||||
def bubble_sort(nums: list[int]) -> None:
|
||||
""" 冒泡排序 """
|
||||
"""冒泡排序"""
|
||||
n: int = len(nums)
|
||||
# 外循环:待排序元素数量为 n-1, n-2, ..., 1
|
||||
for i in range(n - 1, 0, -1):
|
||||
@ -294,7 +294,7 @@ comments: true
|
||||
|
||||
```python title="bubble_sort.py"
|
||||
def bubble_sort_with_flag(nums: list[int]) -> None:
|
||||
""" 冒泡排序(标志优化) """
|
||||
"""冒泡排序(标志优化)"""
|
||||
n: int = len(nums)
|
||||
# 外循环:待排序元素数量为 n-1, n-2, ..., 1
|
||||
for i in range(n - 1, 0, -1):
|
||||
@ -306,7 +306,7 @@ comments: true
|
||||
nums[j], nums[j + 1] = nums[j + 1], nums[j]
|
||||
flag = True # 记录交换元素
|
||||
if not flag:
|
||||
break # 此轮冒泡未交换任何元素,直接跳出
|
||||
break # 此轮冒泡未交换任何元素,直接跳出
|
||||
```
|
||||
|
||||
=== "Go"
|
||||
|
||||
@ -87,6 +87,7 @@ comments: true
|
||||
|
||||
```python title="bucket_sort.py"
|
||||
def bucket_sort(nums: list[float]) -> None:
|
||||
"""桶排序"""
|
||||
# 初始化 k = n/2 个桶,预期向每个桶分配 2 个元素
|
||||
k = len(nums) // 2
|
||||
buckets = [[] for _ in range(k)]
|
||||
|
||||
@ -76,7 +76,7 @@ comments: true
|
||||
|
||||
```python title="counting_sort.py"
|
||||
def counting_sort_naive(nums: list[int]) -> None:
|
||||
""" 计数排序 """
|
||||
"""计数排序"""
|
||||
# 简单实现,无法用于排序对象
|
||||
# 1. 统计数组最大元素 m
|
||||
m = 0
|
||||
@ -346,7 +346,7 @@ $$
|
||||
|
||||
```python title="counting_sort.py"
|
||||
def counting_sort(nums: list[int]) -> None:
|
||||
""" 计数排序 """
|
||||
"""计数排序"""
|
||||
# 完整实现,可排序对象,并且是稳定排序
|
||||
# 1. 统计数组最大元素 m
|
||||
m = max(nums)
|
||||
|
||||
@ -66,8 +66,8 @@ comments: true
|
||||
|
||||
```python title="insertion_sort.py"
|
||||
def insertion_sort(nums: list[int]) -> None:
|
||||
""" 插入排序 """
|
||||
# 外循环:base = nums[1], nums[2], ..., nums[n-1]
|
||||
"""插入排序"""
|
||||
# 外循环:base = nums[1], nums[2], ..., nums[n-1]
|
||||
for i in range(1, len(nums)):
|
||||
base: int = nums[i]
|
||||
j: int = i - 1
|
||||
@ -75,7 +75,7 @@ comments: true
|
||||
while j >= 0 and nums[j] > base:
|
||||
nums[j + 1] = nums[j] # 1. 将 nums[j] 向右移动一位
|
||||
j -= 1
|
||||
nums[j + 1] = base # 2. 将 base 赋值到正确位置
|
||||
nums[j + 1] = base # 2. 将 base 赋值到正确位置
|
||||
```
|
||||
|
||||
=== "Go"
|
||||
|
||||
@ -147,11 +147,11 @@ comments: true
|
||||
|
||||
```python title="merge_sort.py"
|
||||
def merge(nums: list[int], left: int, mid: int, right: int) -> None:
|
||||
""" 合并左子数组和右子数组 """
|
||||
"""合并左子数组和右子数组"""
|
||||
# 左子数组区间 [left, mid]
|
||||
# 右子数组区间 [mid + 1, right]
|
||||
# 初始化辅助数组
|
||||
tmp: list[int] = list(nums[left:right + 1])
|
||||
tmp: list[int] = list(nums[left : right + 1])
|
||||
# 左子数组的起始索引和结束索引
|
||||
left_start: int = 0
|
||||
left_end: int = mid - left
|
||||
@ -177,13 +177,13 @@ comments: true
|
||||
j += 1
|
||||
|
||||
def merge_sort(nums: list[int], left: int, right: int) -> None:
|
||||
""" 归并排序 """
|
||||
"""归并排序"""
|
||||
# 终止条件
|
||||
if left >= right:
|
||||
return # 当子数组长度为 1 时终止递归
|
||||
return # 当子数组长度为 1 时终止递归
|
||||
# 划分阶段
|
||||
mid: int = (left + right) // 2 # 计算中点
|
||||
merge_sort(nums, left, mid) # 递归左子数组
|
||||
mid: int = (left + right) // 2 # 计算中点
|
||||
merge_sort(nums, left, mid) # 递归左子数组
|
||||
merge_sort(nums, mid + 1, right) # 递归右子数组
|
||||
# 合并阶段
|
||||
merge(nums, left, mid, right)
|
||||
|
||||
@ -101,7 +101,7 @@ comments: true
|
||||
|
||||
```python title="quick_sort.py"
|
||||
def partition(self, nums: list[int], left: int, right: int) -> int:
|
||||
""" 哨兵划分 """
|
||||
"""哨兵划分"""
|
||||
# 以 nums[left] 作为基准数
|
||||
i, j = left, right
|
||||
while i < j:
|
||||
@ -334,7 +334,7 @@ comments: true
|
||||
|
||||
```python title="quick_sort.py"
|
||||
def quick_sort(self, nums: list[int], left: int, right: int) -> None:
|
||||
""" 快速排序 """
|
||||
"""快速排序"""
|
||||
# 子数组长度为 1 时终止递归
|
||||
if left >= right:
|
||||
return
|
||||
@ -549,7 +549,7 @@ comments: true
|
||||
|
||||
```python title="quick_sort.py"
|
||||
def median_three(self, nums: list[int], left: int, mid: int, right: int) -> int:
|
||||
""" 选取三个元素的中位数 """
|
||||
"""选取三个元素的中位数"""
|
||||
# 此处使用异或运算来简化代码
|
||||
# 异或规则为 0 ^ 0 = 1 ^ 1 = 0, 0 ^ 1 = 1 ^ 0 = 1
|
||||
if (nums[left] < nums[mid]) ^ (nums[left] < nums[right]):
|
||||
@ -559,7 +559,7 @@ comments: true
|
||||
return right
|
||||
|
||||
def partition(self, nums: list[int], left: int, right: int) -> int:
|
||||
""" 哨兵划分(三数取中值) """
|
||||
"""哨兵划分(三数取中值)"""
|
||||
# 以 nums[left] 作为基准数
|
||||
med: int = self.median_three(nums, left, (left + right) // 2, right)
|
||||
# 将中位数交换至数组最左端
|
||||
@ -842,7 +842,7 @@ comments: true
|
||||
|
||||
```python title="quick_sort.py"
|
||||
def quick_sort(self, nums: list[int], left: int, right: int) -> None:
|
||||
""" 快速排序(尾递归优化) """
|
||||
"""快速排序(尾递归优化)"""
|
||||
# 子数组长度为 1 时终止
|
||||
while left < right:
|
||||
# 哨兵划分操作
|
||||
@ -850,10 +850,10 @@ comments: true
|
||||
# 对两个子数组中较短的那个执行快排
|
||||
if pivot - left < right - pivot:
|
||||
self.quick_sort(nums, left, pivot - 1) # 递归排序左子数组
|
||||
left = pivot + 1 # 剩余待排序区间为 [pivot + 1, right]
|
||||
left = pivot + 1 # 剩余待排序区间为 [pivot + 1, right]
|
||||
else:
|
||||
self.quick_sort(nums, pivot + 1, right) # 递归排序右子数组
|
||||
right = pivot - 1 # 剩余待排序区间为 [left, pivot - 1]
|
||||
right = pivot - 1 # 剩余待排序区间为 [left, pivot - 1]
|
||||
```
|
||||
|
||||
=== "Go"
|
||||
|
||||
@ -136,19 +136,19 @@ $$
|
||||
|
||||
```python title="radix_sort.py"
|
||||
def digit(num: int, exp: int) -> int:
|
||||
""" 获取元素 num 的第 k 位,其中 exp = 10^(k-1) """
|
||||
"""获取元素 num 的第 k 位,其中 exp = 10^(k-1)"""
|
||||
# 传入 exp 而非 k 可以避免在此重复执行昂贵的次方计算
|
||||
return (num // exp) % 10
|
||||
|
||||
def counting_sort_digit(nums: list[int], exp: int) -> None:
|
||||
""" 计数排序(根据 nums 第 k 位排序) """
|
||||
"""计数排序(根据 nums 第 k 位排序)"""
|
||||
# 十进制的位范围为 0~9 ,因此需要长度为 10 的桶
|
||||
counter = [0] * 10
|
||||
n = len(nums)
|
||||
# 统计 0~9 各数字的出现次数
|
||||
for i in range(n):
|
||||
d = digit(nums[i], exp) # 获取 nums[i] 第 k 位,记为 d
|
||||
counter[d] += 1 # 统计数字 d 的出现次数
|
||||
counter[d] += 1 # 统计数字 d 的出现次数
|
||||
# 求前缀和,将“出现个数”转换为“数组索引”
|
||||
for i in range(1, 10):
|
||||
counter[i] += counter[i - 1]
|
||||
@ -157,14 +157,14 @@ $$
|
||||
for i in range(n - 1, -1, -1):
|
||||
d = digit(nums[i], exp)
|
||||
j = counter[d] - 1 # 获取 d 在数组中的索引 j
|
||||
res[j] = nums[i] # 将当前元素填入索引 j
|
||||
counter[d] -= 1 # 将 d 的数量减 1
|
||||
res[j] = nums[i] # 将当前元素填入索引 j
|
||||
counter[d] -= 1 # 将 d 的数量减 1
|
||||
# 使用结果覆盖原数组 nums
|
||||
for i in range(n):
|
||||
nums[i] = res[i]
|
||||
|
||||
def radix_sort(nums: list[int]) -> None:
|
||||
""" 基数排序 """
|
||||
"""基数排序"""
|
||||
# 获取数组的最大元素,用于判断最大位数
|
||||
m = max(nums)
|
||||
# 按照从低位到高位的顺序遍历
|
||||
|
||||
@ -591,31 +591,33 @@ comments: true
|
||||
|
||||
```python title="linkedlist_deque.py"
|
||||
class ListNode:
|
||||
""" 双向链表节点 """
|
||||
"""双向链表节点"""
|
||||
|
||||
def __init__(self, val: int) -> None:
|
||||
""" 构造方法 """
|
||||
"""构造方法"""
|
||||
self.val: int = val
|
||||
self.next: ListNode | None = None # 后继节点引用(指针)
|
||||
self.prev: ListNode | None = None # 前驱节点引用(指针)
|
||||
|
||||
class LinkedListDeque:
|
||||
""" 基于双向链表实现的双向队列 """
|
||||
"""基于双向链表实现的双向队列"""
|
||||
|
||||
def __init__(self) -> None:
|
||||
""" 构造方法 """
|
||||
self.front: ListNode | None = None # 头节点 front
|
||||
"""构造方法"""
|
||||
self.front: ListNode | None = None # 头节点 front
|
||||
self.rear: ListNode | None = None # 尾节点 rear
|
||||
self.__size: int = 0 # 双向队列的长度
|
||||
self.__size: int = 0 # 双向队列的长度
|
||||
|
||||
def size(self) -> int:
|
||||
""" 获取双向队列的长度 """
|
||||
"""获取双向队列的长度"""
|
||||
return self.__size
|
||||
|
||||
def is_empty(self) -> bool:
|
||||
""" 判断双向队列是否为空 """
|
||||
"""判断双向队列是否为空"""
|
||||
return self.size() == 0
|
||||
|
||||
def push(self, num: int, is_front: bool) -> None:
|
||||
""" 入队操作 """
|
||||
"""入队操作"""
|
||||
node = ListNode(num)
|
||||
# 若链表为空,则令 front, rear 都指向 node
|
||||
if self.is_empty():
|
||||
@ -635,15 +637,15 @@ comments: true
|
||||
self.__size += 1 # 更新队列长度
|
||||
|
||||
def push_first(self, num: int) -> None:
|
||||
""" 队首入队 """
|
||||
"""队首入队"""
|
||||
self.push(num, True)
|
||||
|
||||
def push_last(self, num: int) -> None:
|
||||
""" 队尾入队 """
|
||||
"""队尾入队"""
|
||||
self.push(num, False)
|
||||
|
||||
def pop(self, is_front: bool) -> int:
|
||||
""" 出队操作 """
|
||||
"""出队操作"""
|
||||
# 若队列为空,直接返回 None
|
||||
if self.is_empty():
|
||||
return None
|
||||
@ -669,23 +671,23 @@ comments: true
|
||||
return val
|
||||
|
||||
def pop_first(self) -> int:
|
||||
""" 队首出队 """
|
||||
"""队首出队"""
|
||||
return self.pop(True)
|
||||
|
||||
def pop_last(self) -> int:
|
||||
""" 队尾出队 """
|
||||
"""队尾出队"""
|
||||
return self.pop(False)
|
||||
|
||||
def peek_first(self) -> int:
|
||||
""" 访问队首元素 """
|
||||
"""访问队首元素"""
|
||||
return None if self.is_empty() else self.front.val
|
||||
|
||||
def peek_last(self) -> int:
|
||||
""" 访问队尾元素 """
|
||||
"""访问队尾元素"""
|
||||
return None if self.is_empty() else self.rear.val
|
||||
|
||||
def to_array(self) -> list[int]:
|
||||
""" 返回数组用于打印 """
|
||||
"""返回数组用于打印"""
|
||||
node: ListNode | None = self.front
|
||||
res: list[int] = [0] * self.size()
|
||||
for i in range(self.size()):
|
||||
@ -1583,34 +1585,35 @@ comments: true
|
||||
|
||||
```python title="array_deque.py"
|
||||
class ArrayDeque:
|
||||
""" 基于环形数组实现的双向队列 """
|
||||
"""基于环形数组实现的双向队列"""
|
||||
|
||||
def __init__(self, capacity: int) -> None:
|
||||
""" 构造方法 """
|
||||
"""构造方法"""
|
||||
self.__nums: list[int] = [0] * capacity
|
||||
self.__front: int = 0
|
||||
self.__size: int = 0
|
||||
|
||||
def capacity(self) -> int:
|
||||
""" 获取双向队列的容量 """
|
||||
"""获取双向队列的容量"""
|
||||
return len(self.__nums)
|
||||
|
||||
def size(self) -> int:
|
||||
""" 获取双向队列的长度 """
|
||||
"""获取双向队列的长度"""
|
||||
return self.__size
|
||||
|
||||
def is_empty(self) -> bool:
|
||||
""" 判断双向队列是否为空 """
|
||||
"""判断双向队列是否为空"""
|
||||
return self.__size == 0
|
||||
|
||||
def index(self, i: int) -> int:
|
||||
""" 计算环形数组索引 """
|
||||
"""计算环形数组索引"""
|
||||
# 通过取余操作实现数组首尾相连
|
||||
# 当 i 越过数组尾部后,回到头部
|
||||
# 当 i 越过数组头部后,回到尾部
|
||||
return (i + self.capacity()) % self.capacity()
|
||||
|
||||
def push_first(self, num: int) -> None:
|
||||
""" 队首入队 """
|
||||
"""队首入队"""
|
||||
if self.__size == self.capacity():
|
||||
print("双向队列已满")
|
||||
return
|
||||
@ -1622,7 +1625,7 @@ comments: true
|
||||
self.__size += 1
|
||||
|
||||
def push_last(self, num: int) -> None:
|
||||
""" 队尾入队 """
|
||||
"""队尾入队"""
|
||||
if self.__size == self.capacity():
|
||||
print("双向队列已满")
|
||||
return
|
||||
@ -1633,7 +1636,7 @@ comments: true
|
||||
self.__size += 1
|
||||
|
||||
def pop_first(self) -> int:
|
||||
""" 队首出队 """
|
||||
"""队首出队"""
|
||||
num = self.peek_first()
|
||||
# 队首指针向后移动一位
|
||||
self.__front = self.index(self.__front + 1)
|
||||
@ -1641,25 +1644,25 @@ comments: true
|
||||
return num
|
||||
|
||||
def pop_last(self) -> int:
|
||||
""" 队尾出队 """
|
||||
"""队尾出队"""
|
||||
num = self.peek_last()
|
||||
self.__size -= 1
|
||||
return num
|
||||
|
||||
def peek_first(self) -> int:
|
||||
""" 访问队首元素 """
|
||||
"""访问队首元素"""
|
||||
assert not self.is_empty(), "双向队列为空"
|
||||
return self.__nums[self.__front]
|
||||
|
||||
def peek_last(self) -> int:
|
||||
""" 访问队尾元素 """
|
||||
"""访问队尾元素"""
|
||||
assert not self.is_empty(), "双向队列为空"
|
||||
# 计算尾元素索引
|
||||
last = self.index(self.__front + self.__size - 1)
|
||||
return self.__nums[last]
|
||||
|
||||
def to_array(self) -> list[int]:
|
||||
""" 返回数组用于打印 """
|
||||
"""返回数组用于打印"""
|
||||
# 仅转换有效长度范围内的列表元素
|
||||
res = []
|
||||
for i in range(self.__size):
|
||||
|
||||
@ -428,23 +428,24 @@ comments: true
|
||||
|
||||
```python title="linkedlist_queue.py"
|
||||
class LinkedListQueue:
|
||||
""" 基于链表实现的队列 """
|
||||
"""基于链表实现的队列"""
|
||||
|
||||
def __init__(self):
|
||||
""" 构造方法 """
|
||||
"""构造方法"""
|
||||
self.__front: ListNode | None = None # 头节点 front
|
||||
self.__rear: ListNode | None = None # 尾节点 rear
|
||||
self.__rear: ListNode | None = None # 尾节点 rear
|
||||
self.__size: int = 0
|
||||
|
||||
def size(self) -> int:
|
||||
""" 获取队列的长度 """
|
||||
"""获取队列的长度"""
|
||||
return self.__size
|
||||
|
||||
def is_empty(self) -> bool:
|
||||
""" 判断队列是否为空 """
|
||||
"""判断队列是否为空"""
|
||||
return not self.__front
|
||||
|
||||
def push(self, num: int) -> None:
|
||||
""" 入队 """
|
||||
"""入队"""
|
||||
# 尾节点后添加 num
|
||||
node = ListNode(num)
|
||||
# 如果队列为空,则令头、尾节点都指向该节点
|
||||
@ -458,7 +459,7 @@ comments: true
|
||||
self.__size += 1
|
||||
|
||||
def pop(self) -> int:
|
||||
""" 出队 """
|
||||
"""出队"""
|
||||
num = self.peek()
|
||||
# 删除头节点
|
||||
self.__front = self.__front.next
|
||||
@ -466,14 +467,14 @@ comments: true
|
||||
return num
|
||||
|
||||
def peek(self) -> int:
|
||||
""" 访问队首元素 """
|
||||
"""访问队首元素"""
|
||||
if self.size() == 0:
|
||||
print("队列为空")
|
||||
return False
|
||||
return self.__front.val
|
||||
|
||||
def to_list(self) -> list[int]:
|
||||
""" 转化为列表用于打印 """
|
||||
"""转化为列表用于打印"""
|
||||
queue = []
|
||||
temp = self.__front
|
||||
while temp:
|
||||
@ -1103,27 +1104,28 @@ comments: true
|
||||
|
||||
```python title="array_queue.py"
|
||||
class ArrayQueue:
|
||||
""" 基于环形数组实现的队列 """
|
||||
"""基于环形数组实现的队列"""
|
||||
|
||||
def __init__(self, size: int) -> None:
|
||||
""" 构造方法 """
|
||||
"""构造方法"""
|
||||
self.__nums: list[int] = [0] * size # 用于存储队列元素的数组
|
||||
self.__front: int = 0 # 队首指针,指向队首元素
|
||||
self.__size: int = 0 # 队列长度
|
||||
self.__front: int = 0 # 队首指针,指向队首元素
|
||||
self.__size: int = 0 # 队列长度
|
||||
|
||||
def capacity(self) -> int:
|
||||
""" 获取队列的容量 """
|
||||
"""获取队列的容量"""
|
||||
return len(self.__nums)
|
||||
|
||||
def size(self) -> int:
|
||||
""" 获取队列的长度 """
|
||||
"""获取队列的长度"""
|
||||
return self.__size
|
||||
|
||||
def is_empty(self) -> bool:
|
||||
""" 判断队列是否为空 """
|
||||
"""判断队列是否为空"""
|
||||
return self.__size == 0
|
||||
|
||||
def push(self, num: int) -> None:
|
||||
""" 入队 """
|
||||
"""入队"""
|
||||
assert self.__size < self.capacity(), "队列已满"
|
||||
# 计算尾指针,指向队尾索引 + 1
|
||||
# 通过取余操作,实现 rear 越过数组尾部后回到头部
|
||||
@ -1133,7 +1135,7 @@ comments: true
|
||||
self.__size += 1
|
||||
|
||||
def pop(self) -> int:
|
||||
""" 出队 """
|
||||
"""出队"""
|
||||
num: int = self.peek()
|
||||
# 队首指针向后移动一位,若越过尾部则返回到数组头部
|
||||
self.__front = (self.__front + 1) % self.capacity()
|
||||
@ -1141,12 +1143,12 @@ comments: true
|
||||
return num
|
||||
|
||||
def peek(self) -> int:
|
||||
""" 访问队首元素 """
|
||||
"""访问队首元素"""
|
||||
assert not self.is_empty(), "队列为空"
|
||||
return self.__nums[self.__front]
|
||||
|
||||
def to_list(self) -> list[int]:
|
||||
""" 返回列表用于打印 """
|
||||
"""返回列表用于打印"""
|
||||
res: list[int] = [0] * self.size()
|
||||
j: int = self.__front
|
||||
for i in range(self.size()):
|
||||
|
||||
@ -409,42 +409,44 @@ comments: true
|
||||
|
||||
```python title="linkedlist_stack.py"
|
||||
class LinkedListStack:
|
||||
""" 基于链表实现的栈 """
|
||||
"""基于链表实现的栈"""
|
||||
|
||||
def __init__(self):
|
||||
""" 构造方法 """
|
||||
"""构造方法"""
|
||||
self.__peek: ListNode | None = None
|
||||
self.__size: int = 0
|
||||
|
||||
def size(self) -> int:
|
||||
""" 获取栈的长度 """
|
||||
"""获取栈的长度"""
|
||||
return self.__size
|
||||
|
||||
def is_empty(self) -> bool:
|
||||
""" 判断栈是否为空 """
|
||||
"""判断栈是否为空"""
|
||||
return not self.__peek
|
||||
|
||||
def push(self, val: int) -> None:
|
||||
""" 入栈 """
|
||||
"""入栈"""
|
||||
node = ListNode(val)
|
||||
node.next = self.__peek
|
||||
self.__peek = node
|
||||
self.__size += 1
|
||||
|
||||
def pop(self) -> int:
|
||||
""" 出栈 """
|
||||
"""出栈"""
|
||||
num: int = self.peek()
|
||||
self.__peek = self.__peek.next
|
||||
self.__size -= 1
|
||||
return num
|
||||
|
||||
def peek(self) -> int:
|
||||
""" 访问栈顶元素 """
|
||||
"""访问栈顶元素"""
|
||||
# 判空处理
|
||||
if not self.__peek: return None
|
||||
if not self.__peek:
|
||||
return None
|
||||
return self.__peek.val
|
||||
|
||||
def to_list(self) -> list[int]:
|
||||
""" 转化为列表用于打印 """
|
||||
"""转化为列表用于打印"""
|
||||
arr: list[int] = []
|
||||
node = self.__peek
|
||||
while node:
|
||||
@ -951,35 +953,36 @@ comments: true
|
||||
|
||||
```python title="array_stack.py"
|
||||
class ArrayStack:
|
||||
""" 基于数组实现的栈 """
|
||||
"""基于数组实现的栈"""
|
||||
|
||||
def __init__(self) -> None:
|
||||
""" 构造方法 """
|
||||
"""构造方法"""
|
||||
self.__stack: list[int] = []
|
||||
|
||||
def size(self) -> int:
|
||||
""" 获取栈的长度 """
|
||||
"""获取栈的长度"""
|
||||
return len(self.__stack)
|
||||
|
||||
def is_empty(self) -> bool:
|
||||
""" 判断栈是否为空 """
|
||||
"""判断栈是否为空"""
|
||||
return self.__stack == []
|
||||
|
||||
def push(self, item: int) -> None:
|
||||
""" 入栈 """
|
||||
"""入栈"""
|
||||
self.__stack.append(item)
|
||||
|
||||
def pop(self) -> int:
|
||||
""" 出栈 """
|
||||
"""出栈"""
|
||||
assert not self.is_empty(), "栈为空"
|
||||
return self.__stack.pop()
|
||||
|
||||
def peek(self) -> int:
|
||||
""" 访问栈顶元素 """
|
||||
"""访问栈顶元素"""
|
||||
assert not self.is_empty(), "栈为空"
|
||||
return self.__stack[-1]
|
||||
|
||||
|
||||
def to_list(self) -> list[int]:
|
||||
""" 返回列表用于打印 """
|
||||
"""返回列表用于打印"""
|
||||
return self.__stack
|
||||
```
|
||||
|
||||
|
||||
@ -195,14 +195,14 @@ G. M. Adelson-Velsky 和 E. M. Landis 在其 1962 年发表的论文 "An algorit
|
||||
|
||||
```python title="avl_tree.py"
|
||||
def height(self, node: TreeNode | None) -> int:
|
||||
""" 获取节点高度 """
|
||||
"""获取节点高度"""
|
||||
# 空节点高度为 -1 ,叶节点高度为 0
|
||||
if node is not None:
|
||||
return node.height
|
||||
return -1
|
||||
|
||||
def __update_height(self, node: TreeNode | None):
|
||||
""" 更新节点高度 """
|
||||
"""更新节点高度"""
|
||||
# 节点高度等于最高子树高度 + 1
|
||||
node.height = max([self.height(node.left), self.height(node.right)]) + 1
|
||||
```
|
||||
@ -355,7 +355,7 @@ G. M. Adelson-Velsky 和 E. M. Landis 在其 1962 年发表的论文 "An algorit
|
||||
|
||||
```python title="avl_tree.py"
|
||||
def balance_factor(self, node: TreeNode | None) -> int:
|
||||
""" 获取平衡因子 """
|
||||
"""获取平衡因子"""
|
||||
# 空节点平衡因子为 0
|
||||
if node is None:
|
||||
return 0
|
||||
@ -518,7 +518,7 @@ AVL 树的独特之处在于「旋转 Rotation」的操作,其可 **在不影
|
||||
|
||||
```python title="avl_tree.py"
|
||||
def __right_rotate(self, node: TreeNode | None) -> TreeNode | None:
|
||||
""" 右旋操作 """
|
||||
"""右旋操作"""
|
||||
child = node.left
|
||||
grand_child = child.right
|
||||
# 以 child 为原点,将 node 向右旋转
|
||||
@ -702,7 +702,7 @@ AVL 树的独特之处在于「旋转 Rotation」的操作,其可 **在不影
|
||||
|
||||
```python title="avl_tree.py"
|
||||
def __left_rotate(self, node: TreeNode | None) -> TreeNode | None:
|
||||
""" 左旋操作 """
|
||||
"""左旋操作"""
|
||||
child = node.right
|
||||
grand_child = child.left
|
||||
# 以 child 为原点,将 node 向左旋转
|
||||
@ -941,7 +941,7 @@ AVL 树的独特之处在于「旋转 Rotation」的操作,其可 **在不影
|
||||
|
||||
```python title="avl_tree.py"
|
||||
def __rotate(self, node: TreeNode | None) -> TreeNode | None:
|
||||
""" 执行旋转操作,使该子树重新恢复平衡 """
|
||||
"""执行旋转操作,使该子树重新恢复平衡"""
|
||||
# 获取节点 node 的平衡因子
|
||||
balance_factor = self.balance_factor(node)
|
||||
# 左偏树
|
||||
@ -1251,12 +1251,12 @@ AVL 树的独特之处在于「旋转 Rotation」的操作,其可 **在不影
|
||||
|
||||
```python title="avl_tree.py"
|
||||
def insert(self, val) -> TreeNode:
|
||||
""" 插入节点 """
|
||||
"""插入节点"""
|
||||
self.__root = self.__insert_helper(self.__root, val)
|
||||
return self.__root
|
||||
|
||||
def __insert_helper(self, node: TreeNode | None, val: int) -> TreeNode:
|
||||
""" 递归插入节点(辅助方法)"""
|
||||
"""递归插入节点(辅助方法)"""
|
||||
if node is None:
|
||||
return TreeNode(val)
|
||||
# 1. 查找插入位置,并插入节点
|
||||
@ -1576,12 +1576,12 @@ AVL 树的独特之处在于「旋转 Rotation」的操作,其可 **在不影
|
||||
|
||||
```python title="avl_tree.py"
|
||||
def remove(self, val: int) -> TreeNode | None:
|
||||
""" 删除节点 """
|
||||
"""删除节点"""
|
||||
self.__root = self.__remove_helper(self.__root, val)
|
||||
return self.__root
|
||||
return self.__root
|
||||
|
||||
def __remove_helper(self, node: TreeNode | None, val: int) -> TreeNode | None:
|
||||
""" 递归删除节点(辅助方法) """
|
||||
"""递归删除节点(辅助方法)"""
|
||||
if node is None:
|
||||
return None
|
||||
# 1. 查找节点,并删除之
|
||||
@ -1608,7 +1608,7 @@ AVL 树的独特之处在于「旋转 Rotation」的操作,其可 **在不影
|
||||
return self.__rotate(node)
|
||||
|
||||
def __get_inorder_next(self, node: TreeNode | None) -> TreeNode | None:
|
||||
""" 获取中序遍历中的下一个节点(仅适用于 root 有左子节点的情况) """
|
||||
"""获取中序遍历中的下一个节点(仅适用于 root 有左子节点的情况)"""
|
||||
if node is None:
|
||||
return None
|
||||
# 循环访问左子节点,直到叶节点时为最小节点,跳出
|
||||
|
||||
@ -81,7 +81,7 @@ comments: true
|
||||
|
||||
```python title="binary_search_tree.py"
|
||||
def search(self, num: int) -> TreeNode | None:
|
||||
""" 查找节点 """
|
||||
"""查找节点"""
|
||||
cur: TreeNode | None = self.__root
|
||||
# 循环查找,越过叶节点后跳出
|
||||
while cur is not None:
|
||||
@ -309,11 +309,11 @@ comments: true
|
||||
|
||||
```python title="binary_search_tree.py"
|
||||
def insert(self, num: int) -> TreeNode | None:
|
||||
""" 插入节点 """
|
||||
"""插入节点"""
|
||||
# 若树为空,直接提前返回
|
||||
if self.__root is None:
|
||||
return None
|
||||
|
||||
|
||||
# 循环查找,越过叶节点后跳出
|
||||
cur, pre = self.__root, None
|
||||
while cur is not None:
|
||||
@ -692,7 +692,7 @@ comments: true
|
||||
|
||||
```python title="binary_search_tree.py"
|
||||
def remove(self, num: int) -> TreeNode | None:
|
||||
""" 删除节点 """
|
||||
"""删除节点"""
|
||||
# 若树为空,直接提前返回
|
||||
if self.__root is None:
|
||||
return None
|
||||
@ -733,7 +733,7 @@ comments: true
|
||||
return cur
|
||||
|
||||
def get_inorder_next(self, root: TreeNode | None) -> TreeNode | None:
|
||||
""" 获取中序遍历中的下一个节点(仅适用于 root 有左子节点的情况) """
|
||||
"""获取中序遍历中的下一个节点(仅适用于 root 有左子节点的情况)"""
|
||||
if root is None:
|
||||
return root
|
||||
# 循环访问左子节点,直到叶节点时为最小节点,跳出
|
||||
|
||||
@ -70,19 +70,19 @@ comments: true
|
||||
|
||||
```python title="binary_tree_bfs.py"
|
||||
def level_order(root: TreeNode | None) -> list[int]:
|
||||
""" 层序遍历 """
|
||||
"""层序遍历"""
|
||||
# 初始化队列,加入根节点
|
||||
queue: deque[TreeNode] = deque()
|
||||
queue.append(root)
|
||||
# 初始化一个列表,用于保存遍历序列
|
||||
res: list[int] = []
|
||||
while queue:
|
||||
node: TreeNode = queue.popleft() # 队列出队
|
||||
res.append(node.val) # 保存节点值
|
||||
node: TreeNode = queue.popleft() # 队列出队
|
||||
res.append(node.val) # 保存节点值
|
||||
if node.left is not None:
|
||||
queue.append(node.left) # 左子节点入队
|
||||
queue.append(node.left) # 左子节点入队
|
||||
if node.right is not None:
|
||||
queue.append(node.right) # 右子节点入队
|
||||
queue.append(node.right) # 右子节点入队
|
||||
return res
|
||||
```
|
||||
|
||||
@ -338,7 +338,7 @@ comments: true
|
||||
|
||||
```python title="binary_tree_dfs.py"
|
||||
def pre_order(root: TreeNode | None) -> None:
|
||||
""" 前序遍历 """
|
||||
"""前序遍历"""
|
||||
if root is None:
|
||||
return
|
||||
# 访问优先级:根节点 -> 左子树 -> 右子树
|
||||
@ -347,7 +347,7 @@ comments: true
|
||||
pre_order(root=root.right)
|
||||
|
||||
def in_order(root: TreeNode | None) -> None:
|
||||
""" 中序遍历 """
|
||||
"""中序遍历"""
|
||||
if root is None:
|
||||
return
|
||||
# 访问优先级:左子树 -> 根节点 -> 右子树
|
||||
@ -356,7 +356,7 @@ comments: true
|
||||
in_order(root=root.right)
|
||||
|
||||
def post_order(root: TreeNode | None) -> None:
|
||||
""" 后序遍历 """
|
||||
"""后序遍历"""
|
||||
if root is None:
|
||||
return
|
||||
# 访问优先级:左子树 -> 右子树 -> 根节点
|
||||
|
||||
Loading…
Reference in New Issue
Block a user