This commit is contained in:
krahets
2023-03-03 02:46:12 +08:00
parent 122805bdc9
commit cf9d102ed5
24 changed files with 320 additions and 314 deletions

View File

@@ -149,8 +149,8 @@ elementAddr = firtstElementAddr + elementLength * elementIndex
=== "Python"
```python title="array.py"
""" 随机访问元素 """
def random_access(nums):
""" 随机访问元素 """
# 在区间 [0, len(nums)-1] 中随机抽取一个数字
random_index = random.randint(0, len(nums) - 1)
# 获取并返回随机元素
@@ -285,10 +285,8 @@ elementAddr = firtstElementAddr + elementLength * elementIndex
=== "Python"
```python title="array.py"
""" 扩展数组长度 """
# 请注意Python 的 list 是动态数组,可以直接扩展
# 为了方便学习,本函数将 list 看作是长度不可变的数组
def extend(nums, enlarge):
""" 扩展数组长度 """
# 初始化一个扩展长度后的数组
res = [0] * (len(nums) + enlarge)
# 将原数组中的所有元素复制到新数组
@@ -442,8 +440,8 @@ elementAddr = firtstElementAddr + elementLength * elementIndex
=== "Python"
```python title="array.py"
""" 在数组的索引 index 处插入元素 num """
def insert(nums, num, index):
""" 在数组的索引 index 处插入元素 num """
# 把索引 index 以及之后的所有元素向后移动一位
for i in range(len(nums) - 1, index, -1):
nums[i] = nums[i - 1]
@@ -562,8 +560,8 @@ elementAddr = firtstElementAddr + elementLength * elementIndex
=== "Python"
```python title="array.py"
""" 删除索引 index 处元素 """
def remove(nums, index):
""" 删除索引 index 处元素 """
# 把索引 index 之后的所有元素向前移动一位
for i in range(index, len(nums) - 1):
nums[i] = nums[i + 1]
@@ -694,8 +692,8 @@ elementAddr = firtstElementAddr + elementLength * elementIndex
=== "Python"
```python title="array.py"
""" 遍历数组 """
def traverse(nums):
""" 遍历数组 """
count = 0
# 通过索引遍历数组
for i in range(len(nums)):
@@ -850,8 +848,8 @@ elementAddr = firtstElementAddr + elementLength * elementIndex
=== "Python"
```python title="array.py"
""" 在数组中查找指定元素 """
def find(nums, target):
""" 在数组中查找指定元素 """
for i in range(len(nums)):
if nums[i] == target:
return i

View File

@@ -351,8 +351,8 @@ comments: true
=== "Python"
```python title="linked_list.py"
""" 在链表的结点 n0 之后插入结点 P """
def insert(n0, P):
""" 在链表的结点 n0 之后插入结点 P """
n1 = n0.next
P.next = n1
n0.next = P
@@ -470,8 +470,8 @@ comments: true
=== "Python"
```python title="linked_list.py"
""" 删除链表的结点 n0 之后的首个结点 """
def remove(n0):
""" 删除链表的结点 n0 之后的首个结点 """
if not n0.next:
return
# n0 -> P -> n1
@@ -609,8 +609,8 @@ comments: true
=== "Python"
```python title="linked_list.py"
""" 访问链表中索引为 index 的结点 """
def access(head, index):
""" 访问链表中索引为 index 的结点 """
for _ in range(index):
if not head:
return None
@@ -757,8 +757,8 @@ comments: true
=== "Python"
```python title="linked_list.py"
""" 在链表中查找值为 target 的首个结点 """
def find(head, target):
""" 在链表中查找值为 target 的首个结点 """
index = 0
while head:
if head.val == target:

View File

@@ -933,40 +933,45 @@ comments: true
=== "Python"
```python title="my_list.py"
""" 列表类简易实现 """
class MyList:
""" 构造方法 """
""" 列表类简易实现 """
def __init__(self):
""" 构造方法 """
self.__capacity = 10 # 列表容量
self.__nums = [0] * self.__capacity # 数组(存储列表元素)
self.__size = 0 # 列表长度(即当前元素数量)
self.__extend_ratio = 2 # 每次列表扩容的倍数
""" 获取列表长度(即当前元素数量) """
def size(self):
""" 获取列表长度(即当前元素数量) """
return self.__size
""" 获取列表容量 """
def capacity(self):
""" 获取列表容量 """
return self.__capacity
""" 访问元素 """
def get(self, index):
""" 访问元素 """
# 索引如果越界则抛出异常,下同
assert index >= 0 and index < self.__size, "索引越界"
return self.__nums[index]
""" 更新元素 """
def set(self, num, index):
""" 更新元素 """
assert index >= 0 and index < self.__size, "索引越界"
self.__nums[index] = num
def add(self, num):
""" 尾部添加元素 """
# 元素数量超出容量时,触发扩容机制
if self.size() == self.capacity():
self.extend_capacity();
self.__nums[self.__size] = num
self.__size += 1
""" 中间插入(尾部添加)元素 """
def add(self, num, index=-1):
def insert(self, num, index):
""" 中间插入元素 """
assert index >= 0 and index < self.__size, "索引越界"
# 若不指定索引 index ,则向数组尾部添加元素
if index == -1:
index = self.__size
# 元素数量超出容量时,触发扩容机制
if self.__size == self.capacity():
self.extend_capacity()
@@ -977,10 +982,10 @@ comments: true
# 更新元素数量
self.__size += 1
""" 删除元素 """
def remove(self, index):
""" 删除元素 """
assert index >= 0 and index < self.__size, "索引越界"
num = self.nums[index]
num = self.__nums[index]
# 索引 i 之后的元素都向前移动一位
for j in range(index, self.__size - 1):
self.__nums[j] = self.__nums[j + 1]
@@ -989,15 +994,15 @@ comments: true
# 返回被删除元素
return num
""" 列表扩容 """
def extend_capacity(self):
""" 列表扩容 """
# 新建一个长度为 self.__size 的数组,并将原数组拷贝到新数组
self.__nums = self.__nums + [0] * self.capacity() * (self.__extend_ratio - 1)
# 更新列表容量
self.__capacity = len(self.__nums)
""" 返回有效长度的列表 """
def to_array(self):
""" 返回有效长度的列表 """
return self.__nums[:self.__size]
```
@@ -1311,7 +1316,7 @@ comments: true
public toArray(): number[] {
let size = this.size();
// 仅转换有效长度范围内的列表元素
let nums = new Array(size);
const nums = new Array(size);
for (let i = 0; i < size; i++) {
nums[i] = this.get(i);
}

View File

@@ -624,8 +624,8 @@ $$
=== "Python"
```python title="space_complexity.py"
""" 常数阶 """
def constant(n):
""" 常数阶 """
# 常量、变量、对象占用 O(1) 空间
a = 0
nums = [0] * 10000
@@ -829,8 +829,8 @@ $$
=== "Python"
```python title="space_complexity.py"
""" 线性阶 """
def linear(n):
""" 线性阶 """
# 长度为 n 的列表占用 O(n) 空间
nums = [0] * n
# 长度为 n 的哈希表占用 O(n) 空间
@@ -996,8 +996,8 @@ $$
=== "Python"
```python title="space_complexity.py"
""" 线性阶(递归实现) """
def linear_recur(n):
""" 线性阶(递归实现) """
print("递归 n =", n)
if n == 1: return
linear_recur(n - 1)
@@ -1127,8 +1127,8 @@ $$
=== "Python"
```python title="space_complexity.py"
""" 平方阶 """
def quadratic(n):
""" 平方阶 """
# 二维列表占用 O(n^2) 空间
num_matrix = [[0] * n for _ in range(n)]
```
@@ -1171,7 +1171,9 @@ $$
/* 平方阶 */
function quadratic(n: number): void {
// 矩阵占用 O(n^2) 空间
const numMatrix = Array(n).fill(null).map(() => Array(n).fill(null));
const numMatrix = Array(n)
.fill(null)
.map(() => Array(n).fill(null));
// 二维列表占用 O(n^2) 空间
const numList = [];
for (let i = 0; i < n; i++) {
@@ -1273,8 +1275,8 @@ $$
=== "Python"
```python title="space_complexity.py"
""" 平方阶(递归实现) """
def quadratic_recur(n):
""" 平方阶(递归实现) """
if n <= 0: return 0
# 数组 nums 长度为 n, n-1, ..., 2, 1
nums = [0] * n
@@ -1403,8 +1405,8 @@ $$
=== "Python"
```python title="space_complexity.py"
""" 指数阶(建立满二叉树) """
def build_tree(n):
""" 指数阶(建立满二叉树) """
if n == 0: return None
root = TreeNode(0)
root.left = build_tree(n - 1)

View File

@@ -65,8 +65,8 @@ comments: true
=== "Python"
```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)):
@@ -242,8 +242,8 @@ comments: true
=== "Python"
```python title="leetcode_two_sum.py"
""" 方法二:辅助哈希表 """
def two_sum_hash_table(nums: List[int], target: int) -> List[int]:
""" 方法二:辅助哈希表 """
# 辅助哈希表,空间复杂度 O(n)
dic = {}
# 单层循环,时间复杂度 O(n)

View File

@@ -821,8 +821,8 @@ $$
=== "Python"
```python title="time_complexity.py"
""" 常数阶 """
def constant(n):
""" 常数阶 """
count = 0
size = 100000
for _ in range(size):
@@ -949,8 +949,8 @@ $$
=== "Python"
```python title="time_complexity.py"
""" 线性阶 """
def linear(n):
""" 线性阶 """
count = 0
for _ in range(n):
count += 1
@@ -1075,8 +1075,8 @@ $$
=== "Python"
```python title="time_complexity.py"
""" 线性阶(遍历数组)"""
def array_traversal(nums):
""" 线性阶(遍历数组)"""
count = 0
# 循环次数与数组长度成正比
for num in nums:
@@ -1215,8 +1215,8 @@ $$
=== "Python"
```python title="time_complexity.py"
""" 平方阶 """
def quadratic(n):
""" 平方阶 """
count = 0
# 循环次数与数组长度成平方关系
for i in range(n):
@@ -1391,8 +1391,8 @@ $$
=== "Python"
```python title="time_complexity.py"
""" 平方阶(冒泡排序)"""
def bubble_sort(nums):
""" 平方阶(冒泡排序)"""
count = 0 # 计数器
# 外循环:待排序元素数量为 n-1, n-2, ..., 1
for i in range(len(nums) - 1, 0, -1):
@@ -1604,8 +1604,8 @@ $$
=== "Python"
```python title="time_complexity.py"
""" 指数阶(循环实现)"""
def exponential(n):
""" 指数阶(循环实现)"""
count, base = 0, 1
# cell 每轮一分为二,形成数列 1, 2, 4, 8, ..., 2^(n-1)
for _ in range(n):
@@ -1768,8 +1768,8 @@ $$
=== "Python"
```python title="time_complexity.py"
""" 指数阶(递归实现)"""
def exp_recur(n):
""" 指数阶(递归实现)"""
if n == 1: return 1
return exp_recur(n - 1) + exp_recur(n - 1) + 1
```
@@ -1884,8 +1884,8 @@ $$
=== "Python"
```python title="time_complexity.py"
""" 对数阶(循环实现)"""
def logarithmic(n):
""" 对数阶(循环实现)"""
count = 0
while n > 1:
n = n / 2
@@ -2017,8 +2017,8 @@ $$
=== "Python"
```python title="time_complexity.py"
""" 对数阶(递归实现)"""
def log_recur(n):
""" 对数阶(递归实现)"""
if n <= 1: return 0
return log_recur(n / 2) + 1
```
@@ -2133,8 +2133,8 @@ $$
=== "Python"
```python title="time_complexity.py"
""" 线性对数阶 """
def linear_log_recur(n):
""" 线性对数阶 """
if n <= 1: return 1
count = linear_log_recur(n // 2) + \
linear_log_recur(n // 2)
@@ -2290,8 +2290,8 @@ $$
=== "Python"
```python title="time_complexity.py"
""" 阶乘阶(递归实现)"""
def factorial_recur(n):
""" 阶乘阶(递归实现)"""
if n == 0: return 1
count = 0
# 从 1 个分裂出 n 个
@@ -2480,16 +2480,16 @@ $$
=== "Python"
```python title="worst_best_time_complexity.py"
""" 生成一个数组,元素为: 1, 2, ..., n ,顺序被打乱 """
def random_numbers(n):
""" 生成一个数组,元素为: 1, 2, ..., n ,顺序被打乱 """
# 生成数组 nums =: 1, 2, 3, ..., n
nums = [i for i in range(1, n + 1)]
# 随机打乱数组元素
random.shuffle(nums)
return nums
""" 查找数组 nums 中数字 1 所在索引 """
def find_one(nums):
""" 查找数组 nums 中数字 1 所在索引 """
for i in range(len(nums)):
# 当元素 1 在数组头部时,达到最佳时间复杂度 O(1)
# 当元素 1 在数组尾部时,达到最差时间复杂度 O(n)

View File

@@ -127,8 +127,8 @@ comments: true
```cpp title="graph_adjacency_matrix.cpp"
/* 基于邻接矩阵实现的无向图类 */
class GraphAdjMat {
vector<int> vertices; // 顶点列表,元素代表“顶点值”,索引代表“顶点索引”
vector<vector<int>> adjMat; // 邻接矩阵,行列索引对应“顶点索引”
vector<int> vertices; // 顶点列表,元素代表“顶点值”,索引代表“顶点索引”
vector<vector<int>> adjMat; // 邻接矩阵,行列索引对应“顶点索引”
public:
/* 构造方法 */
@@ -213,15 +213,15 @@ comments: true
=== "Python"
```python title="graph_adjacency_matrix.py"
""" 基于邻接矩阵实现的无向图类 """
class GraphAdjMat:
""" 基于邻接矩阵实现的无向图类 """
# 顶点列表,元素代表“顶点值”,索引代表“顶点索引”
vertices = []
# 邻接矩阵,行列索引对应“顶点索引”
adj_mat = []
""" 构造方法 """
def __init__(self, vertices, edges):
""" 构造方法 """
self.vertices = []
self.adj_mat = []
# 添加顶点
@@ -232,12 +232,12 @@ comments: true
for e in edges:
self.add_edge(e[0], e[1])
""" 获取顶点数量 """
def size(self):
""" 获取顶点数量 """
return len(self.vertices)
""" 添加顶点 """
def add_vertex(self, val):
""" 添加顶点 """
n = self.size()
# 向顶点列表中添加新顶点的值
self.vertices.append(val)
@@ -248,9 +248,8 @@ comments: true
for row in self.adj_mat:
row.append(0)
""" 删除顶点 """
def remove_vertex(self, index):
""" 删除顶点 """
if index >= self.size():
raise IndexError()
# 在顶点列表中移除索引 index 的顶点
@@ -261,9 +260,9 @@ comments: true
for row in self.adj_mat:
row.pop(index)
""" 添加边 """
# 参数 i, j 对应 vertices 元素索引
def add_edge(self, i, j):
""" 添加边 """
# 参数 i, j 对应 vertices 元素索引
# 索引越界与相等处理
if i < 0 or j < 0 or i >= self.size() or j >= self.size() or i == j:
raise IndexError()
@@ -271,17 +270,17 @@ comments: true
self.adj_mat[i][j] = 1
self.adj_mat[j][i] = 1
""" 删除边 """
# 参数 i, j 对应 vertices 元素索引
def remove_edge(self, i, j):
""" 删除边 """
# 参数 i, j 对应 vertices 元素索引
# 索引越界与相等处理
if i < 0 or j < 0 or i >= self.size() or j >= self.size() or i == j:
raise IndexError()
self.adj_mat[i][j] = 0
self.adj_mat[j][i] = 0
""" 打印邻接矩阵 """
def print(self):
""" 打印邻接矩阵 """
print("顶点列表 =", self.vertices)
print("邻接矩阵 =")
print_matrix(self.adj_mat)
@@ -964,13 +963,13 @@ comments: true
=== "Python"
```python title="graph_adjacency_list.py"
""" 基于邻接表实现的无向图类 """
class GraphAdjList:
""" 基于邻接表实现的无向图类 """
# 邻接表key: 顶点value该顶点的所有邻接顶点
adj_list = {}
""" 构造方法 """
def __init__(self, edges: List[List[Vertex]]) -> None:
""" 构造方法 """
self.adj_list = {}
# 添加所有顶点和边
for edge in edges:
@@ -978,35 +977,35 @@ comments: true
self.add_vertex(edge[1])
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
self.adj_list[vet1].append(vet2)
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
self.adj_list[vet1].remove(vet2)
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,8 +1015,8 @@ comments: true
if vet in self.adj_list[vertex]:
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]]
@@ -1223,7 +1222,7 @@ comments: true
/* 添加边 */
addEdge(vet1: Vertex, vet2: Vertex): void {
if (!this.adjList.has(vet1) || !this.adjList.has(vet2) || vet1 === vet2) {
throw new Error("Illegal Argument Exception");
throw new Error('Illegal Argument Exception');
}
// 添加边 vet1 - vet2
this.adjList.get(vet1).push(vet2);
@@ -1233,7 +1232,7 @@ comments: true
/* 删除边 */
removeEdge(vet1: Vertex, vet2: Vertex): void {
if (!this.adjList.has(vet1) || !this.adjList.has(vet2) || vet1 === vet2) {
throw new Error("Illegal Argument Exception");
throw new Error('Illegal Argument Exception');
}
// 删除边 vet1 - vet2
this.adjList.get(vet1).splice(this.adjList.get(vet1).indexOf(vet2), 1);
@@ -1250,7 +1249,7 @@ comments: true
/* 删除顶点 */
removeVertex(vet: Vertex): void {
if (!this.adjList.has(vet)) {
throw new Error("Illegal Argument Exception");
throw new Error('Illegal Argument Exception');
}
// 在邻接表中删除顶点 vet 对应的链表
this.adjList.delete(vet);
@@ -1265,13 +1264,13 @@ comments: true
/* 打印邻接表 */
print(): void {
console.log("邻接表 =");
console.log('邻接表 =');
for (const [key, value] of this.adjList.entries()) {
const tmp = [];
for (const vertex of value) {
tmp.push(vertex.val);
}
console.log(key.val + ": " + tmp.join());
console.log(key.val + ': ' + tmp.join());
}
}
}

View File

@@ -93,9 +93,9 @@ BFS 常借助「队列」来实现。队列具有“先入先出”的性质,
=== "Python"
```python title="graph_bfs.py"
""" 广度优先遍历 BFS """
# 使用邻接表来表示图,以便获取指定顶点的所有邻接顶点
def graph_bfs(graph: GraphAdjList, start_vet: Vertex) -> List[Vertex]:
""" 广度优先遍历 BFS """
# 使用邻接表来表示图,以便获取指定顶点的所有邻接顶点
# 顶点遍历序列
res = []
# 哈希表,用于记录已被访问过的顶点
@@ -198,15 +198,15 @@ BFS 常借助「队列」来实现。队列具有“先入先出”的性质,
const que = [startVet];
// 以顶点 vet 为起点,循环直至访问完所有顶点
while (que.length) {
const vet = que.shift(); // 队首顶点出队
res.push(vet); // 记录访问顶点
const vet = que.shift(); // 队首顶点出队
res.push(vet); // 记录访问顶点
// 遍历该顶点的所有邻接顶点
for (const adjVet of graph.adjList.get(vet) ?? []) {
if (visited.has(adjVet)) {
continue; // 跳过已被访问过的顶点
continue; // 跳过已被访问过的顶点
}
que.push(adjVet); // 只入队未访问
visited.add(adjVet); // 标记该顶点已被访问
que.push(adjVet); // 只入队未访问
visited.add(adjVet); // 标记该顶点已被访问
}
}
// 返回顶点遍历序列
@@ -378,8 +378,8 @@ BFS 常借助「队列」来实现。队列具有“先入先出”的性质,
=== "Python"
```python title="graph_dfs.py"
""" 深度优先遍历 DFS 辅助函数 """
def dfs(graph: GraphAdjList, visited: Set[Vertex], res: List[Vertex], vet: Vertex):
""" 深度优先遍历 DFS 辅助函数 """
res.append(vet) # 记录访问顶点
visited.add(vet) # 标记该顶点已被访问
# 遍历该顶点的所有邻接顶点
@@ -389,9 +389,8 @@ BFS 常借助「队列」来实现。队列具有“先入先出”的性质,
# 递归访问邻接顶点
dfs(graph, visited, res, adjVet)
""" 深度优先遍历 DFS """
# 使用邻接表来表示图,以便获取指定顶点的所有邻接顶点
def graph_dfs(graph: GraphAdjList, start_vet: Vertex) -> List[Vertex]:
""" 深度优先遍历 DFS """
# 顶点遍历序列
res = []
# 哈希表,用于记录已被访问过的顶点
@@ -466,8 +465,8 @@ BFS 常借助「队列」来实现。队列具有“先入先出”的性质,
```typescript title="graph_dfs.ts"
/* 深度优先遍历 DFS 辅助函数 */
function dfs(graph: GraphAdjList, visited: Set<Vertex>, res: Vertex[], vet: Vertex): void {
res.push(vet); // 记录访问顶点
visited.add(vet); // 标记该顶点已被访问
res.push(vet); // 记录访问顶点
visited.add(vet); // 标记该顶点已被访问
// 遍历该顶点的所有邻接顶点
for (const adjVet of graph.adjList.get(vet)) {
if (visited.has(adjVet)) {

View File

@@ -604,69 +604,70 @@ $$
=== "Python"
```python title="array_hash_map.py"
""" 键值对 int->String """
class Entry:
""" 键值对 int->String """
def __init__(self, key, val):
self.key = key
self.val = val
""" 基于数组简易实现的哈希表 """
class ArrayHashMap:
""" 基于数组简易实现的哈希表 """
def __init__(self):
""" 构造方法 """
# 初始化一个长度为 100 的桶(数组)
self.bucket = [None] * 100
""" 哈希函数 """
def hash_func(self, key):
""" 哈希函数 """
index = key % 100
return index
""" 查询操作 """
def get(self, key):
""" 查询操作 """
index = self.hash_func(key)
pair = self.bucket[index]
if pair is None:
return None
return pair.val
""" 添加操作 """
def put(self, key, val):
""" 添加操作 """
pair = Entry(key, val)
index = self.hash_func(key)
self.bucket[index] = pair
""" 删除操作 """
def remove(self, key):
""" 删除操作 """
index = self.hash_func(key)
# 置为 None ,代表删除
self.bucket[index] = None
""" 获取所有键值对 """
def entry_set(self):
""" 获取所有键值对 """
result = []
for pair in self.bucket:
if pair is not None:
result.append(pair)
return result
""" 获取所有键 """
def key_set(self):
""" 获取所有键 """
result = []
for pair in self.bucket:
if pair is not None:
result.append(pair.key)
return result
""" 获取所有值 """
def value_set(self):
""" 获取所有值 """
result = []
for pair in self.bucket:
if pair is not None:
result.append(pair.val)
return result
""" 打印哈希表 """
def print(self):
""" 打印哈希表 """
for pair in self.bucket:
if pair is not None:
print(pair.key, "->", pair.val)

View File

@@ -47,8 +47,8 @@ comments: true
=== "Python"
```python title="my_heap.py"
""" 构造方法 """
def __init__(self, nums: List[int]):
""" 构造方法 """
# 将列表元素原封不动添加进堆
self.max_heap = nums
# 堆化除叶结点以外的其他所有结点

View File

@@ -365,16 +365,16 @@ comments: true
=== "Python"
```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 # 向下整除
```
@@ -532,8 +532,8 @@ comments: true
=== "Python"
```python title="my_heap.py"
""" 访问堆顶元素 """
def peek(self) -> int:
""" 访问堆顶元素 """
return self.max_heap[0]
```
@@ -681,15 +681,15 @@ comments: true
=== "Python"
```python title="my_heap.py"
""" 元素入堆 """
def push(self, val: int):
""" 元素入堆 """
# 添加结点
self.max_heap.append(val)
# 从底至顶堆化
self.sift_up(self.size() - 1)
""" 从结点 i 开始,从底至顶堆化 """
def sift_up(self, i: int):
""" 从结点 i 开始,从底至顶堆化 """
while True:
# 获取结点 i 的父结点
p = self.parent(i)
@@ -995,8 +995,8 @@ comments: true
=== "Python"
```python title="my_heap.py"
""" 元素出堆 """
def poll(self) -> int:
""" 元素出堆 """
# 判空处理
assert not self.is_empty()
# 交换根结点与最右叶结点(即交换首元素与尾元素)
@@ -1008,8 +1008,8 @@ comments: true
# 返回堆顶元素
return val
""" 从结点 i 开始,从顶至底堆化 """
def sift_down(self, i: int):
""" 从结点 i 开始,从顶至底堆化 """
while True:
# 判断结点 i, l, r 中值最大的结点,记为 ma
l, r, ma = self.left(i), self.right(i), i
@@ -1113,7 +1113,7 @@ comments: true
/* 元素出堆 */
poll(): number {
// 判空处理
if (this.isEmpty()) throw new RangeError("Heap is empty.");
if (this.isEmpty()) throw new RangeError('Heap is empty.');
// 交换根结点与最右叶结点(即交换首元素与尾元素)
this.swap(0, this.size() - 1);
// 删除结点
@@ -1128,7 +1128,8 @@ comments: true
siftDown(i: number): void {
while (true) {
// 判断结点 i, l, r 中值最大的结点,记为 ma
const l = this.left(i), r = this.right(i);
const l = this.left(i),
r = this.right(i);
let ma = i;
if (l < this.size() && this.maxHeap[l] > this.maxHeap[ma]) ma = l;
if (r < this.size() && this.maxHeap[r] > this.maxHeap[ma]) ma = r;

View File

@@ -98,8 +98,8 @@ $$
=== "Python"
```python title="binary_search.py"
""" 二分查找(双闭区间) """
def binary_search(nums, target):
""" 二分查找(双闭区间) """
# 初始化双闭区间 [0, n-1] ,即 i, j 分别指向数组首元素、尾元素
i, j = 0, len(nums) - 1
while i <= j:
@@ -145,7 +145,7 @@ $$
let i = 0, j = nums.length - 1;
// 循环,当搜索区间为空时跳出(当 i > j 时为空)
while (i <= j) {
let m = parseInt((i + j) / 2); // 计算中点索引 m ,在 JS 中需使用 parseInt 函数取整
const m = parseInt((i + j) / 2); // 计算中点索引 m ,在 JS 中需使用 parseInt 函数取整
if (nums[m] < target) // 此情况说明 target 在区间 [m+1, j] 中
i = m + 1;
else if (nums[m] > target) // 此情况说明 target 在区间 [i, m-1] 中
@@ -167,7 +167,7 @@ $$
let i = 0, j = nums.length - 1;
// 循环,当搜索区间为空时跳出(当 i > j 时为空)
while (i <= j) {
const m = Math.floor(i + (j - i) / 2); // 计算中点索引 m
const m = Math.floor((i + j) / 2); // 计算中点索引 m
if (nums[m] < target) { // 此情况说明 target 在区间 [m+1, j] 中
i = m + 1;
} else if (nums[m] > target) { // 此情况说明 target 在区间 [i, m-1] 中
@@ -309,8 +309,8 @@ $$
=== "Python"
```python title="binary_search.py"
""" 二分查找(左闭右开) """
def binary_search1(nums, target):
""" 二分查找(左闭右开) """
# 初始化左闭右开 [0, n) ,即 i, j 分别指向数组首元素、尾元素+1
i, j = 0, len(nums)
# 循环,当搜索区间为空时跳出(当 i = j 时为空)
@@ -357,7 +357,7 @@ $$
let i = 0, j = nums.length;
// 循环,当搜索区间为空时跳出(当 i = j 时为空)
while (i < j) {
let m = parseInt((i + j) / 2); // 计算中点索引 m ,在 JS 中需使用 parseInt 函数取整
const m = parseInt((i + j) / 2); // 计算中点索引 m ,在 JS 中需使用 parseInt 函数取整
if (nums[m] < target) // 此情况说明 target 在区间 [m+1, j) 中
i = m + 1;
else if (nums[m] > target) // 此情况说明 target 在区间 [i, m) 中
@@ -379,7 +379,7 @@ $$
let i = 0, j = nums.length;
// 循环,当搜索区间为空时跳出(当 i = j 时为空)
while (i < j) {
const m = Math.floor(i + (j - i) / 2); // 计算中点索引 m
const m = Math.floor((i + j) / 2); // 计算中点索引 m
if (nums[m] < target) { // 此情况说明 target 在区间 [m+1, j) 中
i = m + 1;
} else if (nums[m] > target) { // 此情况说明 target 在区间 [i, m) 中

View File

@@ -45,8 +45,8 @@ comments: true
=== "Python"
```python title="hashing_search.py"
""" 哈希查找(数组) """
def hashing_search_array(mapp, target):
""" 哈希查找(数组) """
# 哈希表的 key: 目标元素value: 索引
# 若哈希表中无此 key ,返回 -1
return mapp.get(target, -1)
@@ -85,7 +85,7 @@ comments: true
function hashingSearchArray(map: Map<number, number>, target: number): number {
// 哈希表的 key: 目标元素value: 索引
// 若哈希表中无此 key ,返回 -1
return map.has(target) ? map.get(target) as number : -1;
return map.has(target) ? (map.get(target) as number) : -1;
}
```
@@ -163,8 +163,8 @@ comments: true
=== "Python"
```python title="hashing_search.py"
""" 哈希查找(链表) """
def hashing_search_linkedlist(mapp, target):
""" 哈希查找(链表) """
# 哈希表的 key: 目标元素value: 结点对象
# 若哈希表中无此 key ,返回 -1
return mapp.get(target, -1)
@@ -203,7 +203,7 @@ comments: true
function hashingSearchLinkedList(map: Map<number, ListNode>, target: number): ListNode | null {
// 哈希表的 key: 目标结点值value: 结点对象
// 若哈希表中无此 key ,返回 null
return map.has(target) ? map.get(target) as ListNode : null;
return map.has(target) ? (map.get(target) as ListNode) : null;
}
```

View File

@@ -49,8 +49,8 @@ comments: true
=== "Python"
```python title="linear_search.py"
""" 线性查找(数组) """
def linear_search_array(nums, target):
""" 线性查找(数组) """
# 遍历数组
for i in range(len(nums)):
if nums[i] == target: # 找到目标元素,返回其索引
@@ -206,8 +206,8 @@ comments: true
=== "Python"
```python title="linear_search.py"
""" 线性查找(链表) """
def linear_search_linkedlist(head, target):
""" 线性查找(链表) """
# 遍历链表
while head:
if head.val == target: # 找到目标结点,返回之

View File

@@ -87,8 +87,8 @@ comments: true
=== "Python"
```python title="bubble_sort.py"
""" 冒泡排序 """
def bubble_sort(nums):
""" 冒泡排序 """
n = len(nums)
# 外循环:待排序元素数量为 n-1, n-2, ..., 1
for i in range(n - 1, 0, -1):
@@ -295,8 +295,8 @@ comments: true
=== "Python"
```python title="bubble_sort.py"
""" 冒泡排序(标志优化) """
def bubble_sort_with_flag(nums):
""" 冒泡排序(标志优化) """
n = len(nums)
# 外循环:待排序元素数量为 n-1, n-2, ..., 1
for i in range(n - 1, 0, -1):

View File

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

View File

@@ -146,10 +146,10 @@ comments: true
=== "Python"
```python title="merge_sort.py"
""" 合并左子数组和右子数组 """
# 左子数组区间 [left, mid]
# 右子数组区间 [mid + 1, right]
def merge(nums, left, mid, right):
""" 合并左子数组和右子数组 """
# 左子数组区间 [left, mid]
# 右子数组区间 [mid + 1, right]
# 初始化辅助数组 借助 copy模块
tmp = nums[left:right + 1]
# 左子数组的起始索引和结束索引
@@ -173,8 +173,8 @@ comments: true
nums[k] = tmp[j]
j += 1
""" 归并排序 """
def merge_sort(nums, left, right):
""" 归并排序 """
# 终止条件
if left >= right:
return # 当子数组长度为 1 时终止递归

View File

@@ -100,8 +100,8 @@ comments: true
=== "Python"
```python title="quick_sort.py"
""" 哨兵划分 """
def partition(self, nums, left, right):
""" 哨兵划分 """
# 以 nums[left] 作为基准数
i, j = left, right
while i < j:
@@ -333,8 +333,8 @@ comments: true
=== "Python"
```python title="quick_sort.py"
""" 快速排序 """
def quick_sort(self, nums, left, right):
""" 快速排序 """
# 子数组长度为 1 时终止递归
if left >= right:
return
@@ -552,8 +552,8 @@ comments: true
=== "Python"
```python title="quick_sort.py"
""" 选取三个元素的中位数 """
def median_three(self, nums, left, mid, right):
""" 选取三个元素的中位数 """
# 此处使用异或运算来简化代码
# 异或规则为 0 ^ 0 = 1 ^ 1 = 0, 0 ^ 1 = 1 ^ 0 = 1
if (nums[left] < nums[mid]) ^ (nums[left] < nums[right]):
@@ -562,8 +562,8 @@ comments: true
return mid
return right
""" 哨兵划分(三数取中值) """
def partition(self, nums, left, right):
""" 哨兵划分(三数取中值) """
# 以 nums[left] 作为基准数
med = self.median_three(nums, left, (left + right) // 2, right)
# 将中位数交换至数组最左端
@@ -845,8 +845,8 @@ comments: true
=== "Python"
```python title="quick_sort.py"
""" 快速排序(尾递归优化) """
def quick_sort(self, nums, left, right):
""" 快速排序(尾递归优化) """
# 子数组长度为 1 时终止
while left < right:
# 哨兵划分操作

View File

@@ -590,30 +590,31 @@ comments: true
=== "Python"
```python title="linkedlist_deque.py"
""" 双向链表结点 """
class ListNode:
""" 双向链表结点 """
def __init__(self, val):
""" 构造方法 """
self.val = val
self.next = None # 后继结点引用(指针)
self.prev = None # 前驱结点引用(指针)
""" 基于双向链表实现的双向队列 """
class LinkedListDeque:
""" 构造方法 """
""" 基于双向链表实现的双向队列 """
def __init__(self):
""" 构造方法 """
self.front, self.rear = None, None # 头结点 front ,尾结点 rear
self.__size = 0 # 双向队列的长度
""" 获取双向队列的长度 """
def size(self):
""" 获取双向队列的长度 """
return self.__size
""" 判断双向队列是否为空 """
def is_empty(self):
""" 判断双向队列是否为空 """
return self.size() == 0
""" 入队操作 """
def push(self, num, is_front):
""" 入队操作 """
node = ListNode(num)
# 若链表为空,则令 front, rear 都指向 node
if self.is_empty():
@@ -632,16 +633,16 @@ comments: true
self.rear = node # 更新尾结点
self.__size += 1 # 更新队列长度
""" 队首入队 """
def push_first(self, num):
""" 队首入队 """
self.push(num, True)
""" 队尾入队 """
def push_last(self, num):
""" 队尾入队 """
self.push(num, False)
""" 出队操作 """
def poll(self, is_front):
""" 出队操作 """
# 若队列为空,直接返回 None
if self.is_empty():
return None
@@ -666,24 +667,24 @@ comments: true
self.__size -= 1 # 更新队列长度
return val
""" 队首出队 """
def poll_first(self):
""" 队首出队 """
return self.poll(True)
""" 队尾出队 """
def poll_last(self):
""" 队尾出队 """
return self.poll(False)
""" 访问队首元素 """
def peek_first(self):
""" 访问队首元素 """
return None if self.is_empty() else self.front.val
""" 访问队尾元素 """
def peek_last(self):
""" 访问队尾元素 """
return None if self.is_empty() else self.rear.val
""" 返回数组用于打印 """
def to_array(self):
""" 返回数组用于打印 """
node = self.front
res = [0] * self.size()
for i in range(self.size()):
@@ -790,106 +791,106 @@ comments: true
/* 基于双向链表实现的双向队列 */
class LinkedListDeque {
front; // 头结点 front
rear; // 尾结点 rear
len; // 双向队列的长度
#front; // 头结点 front
#rear; // 尾结点 rear
#queSize; // 双向队列的长度
constructor() {
this.front = null;
this.rear = null;
this.len = 0;
this.#front = null;
this.#rear = null;
this.#queSize = 0;
}
/* 队尾入队操作 */
pushLast(val) {
const node = new ListNode(val);
// 若链表为空,则令 front, rear 都指向 node
if (this.len === 0) {
this.front = node;
this.rear = node;
if (this.#queSize === 0) {
this.#front = node;
this.#rear = node;
} else {
// 将 node 添加至链表尾部
this.rear.next = node;
node.prev = this.rear;
this.rear = node; // 更新尾结点
this.#rear.next = node;
node.prev = this.#rear;
this.#rear = node; // 更新尾结点
}
this.len++;
this.#queSize++;
}
/* 队首入队操作 */
pushFirst(val) {
const node = new ListNode(val);
// 若链表为空,则令 front, rear 都指向 node
if (this.len === 0) {
this.front = node;
this.rear = node;
if (this.#queSize === 0) {
this.#front = node;
this.#rear = node;
} else {
// 将 node 添加至链表头部
this.front.prev = node;
node.next = this.front;
this.front = node; // 更新头结点
this.#front.prev = node;
node.next = this.#front;
this.#front = node; // 更新头结点
}
this.len++;
this.#queSize++;
}
/* 队尾出队操作 */
pollLast() {
if (this.len === 0) {
if (this.#queSize === 0) {
return null;
}
const value = this.rear.val; // 存储尾结点值
const value = this.#rear.val; // 存储尾结点值
// 删除尾结点
let temp = this.rear.prev;
let temp = this.#rear.prev;
if (temp !== null) {
temp.next = null;
this.rear.prev = null;
this.#rear.prev = null;
}
this.rear = temp; // 更新尾结点
this.len--;
this.#rear = temp; // 更新尾结点
this.#queSize--;
return value;
}
/* 队首出队操作 */
pollFirst() {
if (this.len === 0) {
if (this.#queSize === 0) {
return null;
}
const value = this.front.val; // 存储尾结点值
const value = this.#front.val; // 存储尾结点值
// 删除头结点
let temp = this.front.next;
let temp = this.#front.next;
if (temp !== null) {
temp.prev = null;
this.front.next = null;
this.#front.next = null;
}
this.front = temp; // 更新头结点
this.len--;
this.#front = temp; // 更新头结点
this.#queSize--;
return value;
}
/* 访问队尾元素 */
peekLast() {
return this.len === 0 ? null : this.rear.val;
return this.#queSize === 0 ? null : this.#rear.val;
}
/* 访问队首元素 */
peekFirst() {
return this.len === 0 ? null : this.front.val;
return this.#queSize === 0 ? null : this.#front.val;
}
/* 获取双向队列的长度 */
size() {
return this.len;
return this.#queSize;
}
/* 判断双向队列是否为空 */
isEmpty() {
return this.len === 0;
return this.#queSize === 0;
}
/* 打印双向队列 */
print() {
const arr = [];
let temp = this.front;
let temp = this.#front;
while (temp !== null) {
arr.push(temp.val);
temp = temp.next;
@@ -917,21 +918,21 @@ comments: true
/* 基于双向链表实现的双向队列 */
class LinkedListDeque {
front: ListNode; // 头结点 front
rear: ListNode; // 尾结点 rear
len: number; // 双向队列的长度
private front: ListNode; // 头结点 front
private rear: ListNode; // 尾结点 rear
private queSize: number; // 双向队列的长度
constructor() {
this.front = null;
this.rear = null;
this.len = 0;
this.queSize = 0;
}
/* 队尾入队操作 */
pushLast(val: number): void {
const node: ListNode = new ListNode(val);
// 若链表为空,则令 front, rear 都指向 node
if (this.len === 0) {
if (this.queSize === 0) {
this.front = node;
this.rear = node;
} else {
@@ -940,14 +941,14 @@ comments: true
node.prev = this.rear;
this.rear = node; // 更新尾结点
}
this.len++;
this.queSize++;
}
/* 队首入队操作 */
pushFirst(val: number): void {
const node: ListNode = new ListNode(val);
// 若链表为空,则令 front, rear 都指向 node
if (this.len === 0) {
if (this.queSize === 0) {
this.front = node;
this.rear = node;
} else {
@@ -956,12 +957,12 @@ comments: true
node.next = this.front;
this.front = node; // 更新头结点
}
this.len++;
this.queSize++;
}
/* 队尾出队操作 */
pollLast(): number {
if (this.len === 0) {
if (this.queSize === 0) {
return null;
}
const value: number = this.rear.val; // 存储尾结点值
@@ -972,13 +973,13 @@ comments: true
this.rear.prev = null;
}
this.rear = temp; // 更新尾结点
this.len--;
this.queSize--;
return value;
}
/* 队首出队操作 */
pollFirst(): number {
if (this.len === 0) {
if (this.queSize === 0) {
return null;
}
const value: number = this.front.val; // 存储尾结点值
@@ -989,28 +990,28 @@ comments: true
this.front.next = null;
}
this.front = temp; // 更新头结点
this.len--;
this.queSize--;
return value;
}
/* 访问队尾元素 */
peekLast(): number {
return this.len === 0 ? null : this.rear.val;
return this.queSize === 0 ? null : this.rear.val;
}
/* 访问队首元素 */
peekFirst(): number {
return this.len === 0 ? null : this.front.val;
return this.queSize === 0 ? null : this.front.val;
}
/* 获取双向队列的长度 */
size(): number {
return this.len;
return this.queSize;
}
/* 判断双向队列是否为空 */
isEmpty(): boolean {
return this.len === 0;
return this.queSize === 0;
}
/* 打印双向队列 */
@@ -1593,35 +1594,35 @@ comments: true
=== "Python"
```python title="array_deque.py"
""" 基于环形数组实现的双向队列 """
class ArrayDeque:
""" 构造方法 """
""" 基于环形数组实现的双向队列 """
def __init__(self, capacity):
""" 构造方法 """
self.nums = [0] * capacity
self.front = 0
self.que_size = 0
""" 获取双向队列的容量 """
def capacity(self):
""" 获取双向队列的容量 """
return len(self.nums)
""" 获取双向队列的长度 """
def size(self):
""" 获取双向队列的长度 """
return self.que_size
""" 判断双向队列是否为空 """
def is_empty(self):
""" 判断双向队列是否为空 """
return self.que_size == 0
""" 计算环形数组索引 """
def index(self, i):
""" 计算环形数组索引 """
# 通过取余操作实现数组首尾相连
# 当 i 越过数组尾部后,回到头部
# 当 i 越过数组头部后,回到尾部
return (i + self.capacity()) % self.capacity()
""" 队首入队 """
def push_first(self, num):
""" 队首入队 """
if self.que_size == self.capacity():
print("双向队列已满")
return
@@ -1632,8 +1633,8 @@ comments: true
self.nums[self.front] = num
self.que_size += 1
""" 队尾入队 """
def push_last(self, num):
""" 队尾入队 """
if self.que_size == self.capacity():
print("双向队列已满")
return
@@ -1643,34 +1644,34 @@ comments: true
self.nums[rear] = num
self.que_size += 1
""" 队首出队 """
def poll_first(self):
""" 队首出队 """
num = self.peek_first()
# 队首指针向后移动一位
self.front = self.index(self.front+1)
self.que_size -= 1
return num
""" 队尾出队 """
def poll_last(self):
""" 队尾出队 """
num = self.peek_last()
self.que_size -= 1
return num
""" 访问队首元素 """
def peek_first(self):
""" 访问队首元素 """
assert not self.is_empty(), "双向队列为空"
return self.nums[self.front]
""" 访问队尾元素 """
def peek_last(self):
""" 访问队尾元素 """
assert not self.is_empty(), "双向队列为空"
# 计算尾元素索引
last = self.index(self.front + self.que_size - 1)
return self.nums[last]
""" 返回数组用于打印 """
def to_array(self):
""" 返回数组用于打印 """
# 仅转换有效长度范围内的列表元素
res = []
for i in range(self.que_size):

View File

@@ -429,23 +429,24 @@ comments: true
=== "Python"
```python title="linkedlist_queue.py"
""" 基于链表实现的队列 """
class LinkedListQueue:
""" 基于链表实现的队列 """
def __init__(self):
""" 构造方法 """
self.__front = None # 头结点 front
self.__rear = None # 尾结点 rear
self.__size = 0
""" 获取队列的长度 """
def size(self):
""" 获取队列的长度 """
return self.__size
""" 判断队列是否为空 """
def is_empty(self):
""" 判断队列是否为空 """
return not self.__front
""" 入队 """
def push(self, num):
""" 入队 """
# 尾结点后添加 num
node = ListNode(num)
# 如果队列为空,则令头、尾结点都指向该结点
@@ -458,23 +459,23 @@ comments: true
self.__rear = node
self.__size += 1
""" 出队 """
def poll(self):
""" 出队 """
num = self.peek()
# 删除头结点
self.__front = self.__front.next
self.__size -= 1
return num
""" 访问队首元素 """
def peek(self):
""" 访问队首元素 """
if self.size() == 0:
print("队列为空")
return False
return self.__front.val
""" 转化为列表用于打印 """
def to_list(self):
""" 转化为列表用于打印 """
queue = []
temp = self.__front
while temp:
@@ -614,7 +615,7 @@ comments: true
/* 基于链表实现的队列 */
class LinkedListQueue {
private front: ListNode | null; // 头结点 front
private rear: ListNode | null; // 尾结点 rear
private rear: ListNode | null; // 尾结点 rear
private queSize: number = 0;
constructor() {
@@ -651,8 +652,7 @@ comments: true
/* 出队 */
poll(): number {
const num = this.peek();
if (!this.front)
throw new Error("队列为空")
if (!this.front) throw new Error('队列为空');
// 删除头结点
this.front = this.front.next;
this.queSize--;
@@ -661,8 +661,7 @@ comments: true
/* 访问队首元素 */
peek(): number {
if (this.size === 0)
throw new Error("队列为空");
if (this.size === 0) throw new Error('队列为空');
return this.front!.val;
}
@@ -1105,27 +1104,28 @@ comments: true
=== "Python"
```python title="array_queue.py"
""" 基于环形数组实现的队列 """
class ArrayQueue:
""" 基于环形数组实现的队列 """
def __init__(self, size):
""" 构造方法 """
self.__nums = [0] * size # 用于存储队列元素的数组
self.__front = 0 # 队首指针,指向队首元素
self.__size = 0 # 队列长度
""" 获取队列的容量 """
def capacity(self):
""" 获取队列的容量 """
return len(self.__nums)
""" 获取队列的长度 """
def size(self):
""" 获取队列的长度 """
return self.__size
""" 判断队列是否为空 """
def is_empty(self):
""" 判断队列是否为空 """
return self.__size == 0
""" 入队 """
def push(self, num):
""" 入队 """
assert self.__size < self.capacity(), "队列已满"
# 计算尾指针,指向队尾索引 + 1
# 通过取余操作,实现 rear 越过数组尾部后回到头部
@@ -1134,21 +1134,21 @@ comments: true
self.__nums[rear] = num
self.__size += 1
""" 出队 """
def poll(self):
""" 出队 """
num = self.peek()
# 队首指针向后移动一位,若越过尾部则返回到数组头部
self.__front = (self.__front + 1) % self.capacity()
self.__size -= 1
return num
""" 访问队首元素 """
def peek(self):
""" 访问队首元素 """
assert not self.is_empty(), "队列为空"
return self.__nums[self.__front]
""" 返回列表用于打印 """
def to_list(self):
""" 返回列表用于打印 """
res = [0] * self.size()
j = self.__front
for i in range(self.size()):

View File

@@ -410,42 +410,43 @@ comments: true
=== "Python"
```python title="linkedlist_stack.py"
""" 基于链表实现的栈 """
class LinkedListStack:
""" 基于链表实现的栈 """
def __init__(self):
""" 构造方法 """
self.__peek = None
self.__size = 0
""" 获取栈的长度 """
def size(self):
""" 获取栈的长度 """
return self.__size
""" 判断栈是否为空 """
def is_empty(self):
""" 判断栈是否为空 """
return not self.__peek
""" 入栈 """
def push(self, val):
""" 入栈 """
node = ListNode(val)
node.next = self.__peek
self.__peek = node
self.__size += 1
""" 出栈 """
def pop(self):
""" 出栈 """
num = self.peek()
self.__peek = self.__peek.next
self.__size -= 1
return num
""" 访问栈顶元素 """
def peek(self):
""" 访问栈顶元素 """
# 判空处理
if not self.__peek: return None
return self.__peek.val
""" 转化为列表用于打印 """
def to_list(self):
""" 转化为列表用于打印 """
arr = []
node = self.__peek
while node:
@@ -574,8 +575,8 @@ comments: true
```typescript title="linkedlist_stack.ts"
/* 基于链表实现的栈 */
class LinkedListStack {
private stackPeek: ListNode | null; // 将头结点作为栈顶
private stkSize: number = 0; // 栈的长度
private stackPeek: ListNode | null; // 将头结点作为栈顶
private stkSize: number = 0; // 栈的长度
constructor() {
this.stackPeek = null;
@@ -602,8 +603,7 @@ comments: true
/* 出栈 */
pop(): number {
const num = this.peek();
if (!this.stackPeek)
throw new Error("栈为空");
if (!this.stackPeek) throw new Error('栈为空');
this.stackPeek = this.stackPeek.next;
this.stkSize--;
return num;
@@ -611,8 +611,7 @@ comments: true
/* 访问栈顶元素 */
peek(): number {
if (!this.stackPeek)
throw new Error("栈为空");
if (!this.stackPeek) throw new Error('栈为空');
return this.stackPeek.val;
}
@@ -953,35 +952,36 @@ comments: true
=== "Python"
```python title="array_stack.py"
""" 基于数组实现的栈 """
class ArrayStack:
""" 基于数组实现的栈 """
def __init__(self):
""" 构造方法 """
self.__stack = []
""" 获取栈的长度 """
def size(self):
""" 获取栈的长度 """
return len(self.__stack)
""" 判断栈是否为空 """
def is_empty(self):
""" 判断栈是否为空 """
return self.__stack == []
""" 入栈 """
def push(self, item):
""" 入栈 """
self.__stack.append(item)
""" 出栈 """
def pop(self):
""" 出栈 """
assert not self.is_empty(), "栈为空"
return self.__stack.pop()
""" 访问栈顶元素 """
def peek(self):
""" 访问栈顶元素 """
assert not self.is_empty(), "栈为空"
return self.__stack[-1]
""" 返回列表用于打印 """
def to_list(self):
""" 返回列表用于打印 """
return self.__stack
```
@@ -1044,43 +1044,43 @@ comments: true
```javascript title="array_stack.js"
/* 基于数组实现的栈 */
class ArrayStack {
stack;
#stack;
constructor() {
this.stack = [];
this.#stack = [];
}
/* 获取栈的长度 */
get size() {
return this.stack.length;
return this.#stack.length;
}
/* 判断栈是否为空 */
empty() {
return this.stack.length === 0;
return this.#stack.length === 0;
}
/* 入栈 */
push(num) {
this.stack.push(num);
this.#stack.push(num);
}
/* 出栈 */
pop() {
if (this.empty())
throw new Error("栈为空");
return this.stack.pop();
return this.#stack.pop();
}
/* 访问栈顶元素 */
top() {
if (this.empty())
throw new Error("栈为空");
return this.stack[this.stack.length - 1];
return this.#stack[this.#stack.length - 1];
}
/* 返回 Array */
toArray() {
return this.stack;
return this.#stack;
}
};
```

View File

@@ -194,15 +194,15 @@ G. M. Adelson-Velsky 和 E. M. Landis 在其 1962 年发表的论文 "An algorit
=== "Python"
```python title="avl_tree.py"
""" 获取结点高度 """
def height(self, node: Optional[TreeNode]) -> int:
""" 获取结点高度 """
# 空结点高度为 -1 ,叶结点高度为 0
if node is not None:
return node.height
return -1
""" 更新结点高度 """
def __update_height(self, node: Optional[TreeNode]):
""" 更新结点高度 """
# 结点高度等于最高子树高度 + 1
node.height = max([self.height(node.left), self.height(node.right)]) + 1
```
@@ -242,7 +242,7 @@ G. M. Adelson-Velsky 和 E. M. Landis 在其 1962 年发表的论文 "An algorit
}
/* 更新结点高度 */
updateHeight(node) {
#updateHeight(node) {
// 结点高度等于最高子树高度 + 1
node.height = Math.max(this.height(node.left), this.height(node.right)) + 1;
}
@@ -354,8 +354,8 @@ G. M. Adelson-Velsky 和 E. M. Landis 在其 1962 年发表的论文 "An algorit
=== "Python"
```python title="avl_tree.py"
""" 获取平衡因子 """
def balance_factor(self, node: Optional[TreeNode]) -> int:
""" 获取平衡因子 """
# 空结点平衡因子为 0
if node is None:
return 0
@@ -517,8 +517,8 @@ AVL 树的独特之处在于「旋转 Rotation」的操作其可 **在不影
=== "Python"
```python title="avl_tree.py"
""" 右旋操作 """
def __right_rotate(self, node: Optional[TreeNode]) -> TreeNode:
""" 右旋操作 """
child = node.left
grand_child = child.right
# 以 child 为原点,将 node 向右旋转
@@ -553,15 +553,15 @@ AVL 树的独特之处在于「旋转 Rotation」的操作其可 **在不影
```javascript title="avl_tree.js"
/* 右旋操作 */
rightRotate(node) {
#rightRotate(node) {
const child = node.left;
const grandChild = child.right;
// 以 child 为原点,将 node 向右旋转
child.right = node;
node.left = grandChild;
// 更新结点高度
this.updateHeight(node);
this.updateHeight(child);
this.#updateHeight(node);
this.#updateHeight(child);
// 返回旋转后子树的根结点
return child;
}
@@ -701,8 +701,8 @@ AVL 树的独特之处在于「旋转 Rotation」的操作其可 **在不影
=== "Python"
```python title="avl_tree.py"
""" 左旋操作 """
def __left_rotate(self, node: Optional[TreeNode]) -> TreeNode:
""" 左旋操作 """
child = node.right
grand_child = child.left
# 以 child 为原点,将 node 向左旋转
@@ -737,15 +737,15 @@ AVL 树的独特之处在于「旋转 Rotation」的操作其可 **在不影
```javascript title="avl_tree.js"
/* 左旋操作 */
leftRotate(node) {
#leftRotate(node) {
const child = node.right;
const grandChild = child.left;
// 以 child 为原点,将 node 向左旋转
child.left = node;
node.right = grandChild;
// 更新结点高度
this.updateHeight(node);
this.updateHeight(child);
this.#updateHeight(node);
this.#updateHeight(child);
// 返回旋转后子树的根结点
return child;
}
@@ -940,8 +940,8 @@ AVL 树的独特之处在于「旋转 Rotation」的操作其可 **在不影
=== "Python"
```python title="avl_tree.py"
""" 执行旋转操作,使该子树重新恢复平衡 """
def __rotate(self, node: Optional[TreeNode]) -> TreeNode:
""" 执行旋转操作,使该子树重新恢复平衡 """
# 获取结点 node 的平衡因子
balance_factor = self.balance_factor(node)
# 左偏树
@@ -1005,29 +1005,29 @@ AVL 树的独特之处在于「旋转 Rotation」的操作其可 **在不影
```javascript title="avl_tree.js"
/* 执行旋转操作,使该子树重新恢复平衡 */
rotate(node) {
#rotate(node) {
// 获取结点 node 的平衡因子
const balanceFactor = this.balanceFactor(node);
// 左偏树
if (balanceFactor > 1) {
if (this.balanceFactor(node.left) >= 0) {
// 右旋
return this.rightRotate(node);
return this.#rightRotate(node);
} else {
// 先左旋后右旋
node.left = this.leftRotate(node.left);
return this.rightRotate(node);
node.left = this.#leftRotate(node.left);
return this.#rightRotate(node);
}
}
// 右偏树
if (balanceFactor < -1) {
if (this.balanceFactor(node.right) <= 0) {
// 左旋
return this.leftRotate(node);
return this.#leftRotate(node);
} else {
// 先右旋后左旋
node.right = this.rightRotate(node.right);
return this.leftRotate(node);
node.right = this.#rightRotate(node.right);
return this.#leftRotate(node);
}
}
// 平衡树,无需旋转,直接返回
@@ -1249,13 +1249,13 @@ AVL 树的独特之处在于「旋转 Rotation」的操作其可 **在不影
=== "Python"
```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: Optional[TreeNode], val: int) -> TreeNode:
""" 递归插入结点(辅助方法)"""
if node is None:
return TreeNode(val)
# 1. 查找插入位置,并插入结点
@@ -1309,20 +1309,20 @@ AVL 树的独特之处在于「旋转 Rotation」的操作其可 **在不影
```javascript title="avl_tree.js"
/* 插入结点 */
insert(val) {
this.root = this.insertHelper(this.root, val);
this.root = this.#insertHelper(this.root, val);
return this.root;
}
/* 递归插入结点(辅助方法) */
insertHelper(node, val) {
#insertHelper(node, val) {
if (node === null) return new TreeNode(val);
/* 1. 查找插入位置,并插入结点 */
if (val < node.val) node.left = this.insertHelper(node.left, val);
else if (val > node.val) node.right = this.insertHelper(node.right, val);
if (val < node.val) node.left = this.#insertHelper(node.left, val);
else if (val > node.val) node.right = this.#insertHelper(node.right, val);
else return node; // 重复结点不插入,直接返回
this.updateHeight(node); // 更新结点高度
this.#updateHeight(node); // 更新结点高度
/* 2. 执行旋转操作,使该子树重新恢复平衡 */
node = this.rotate(node);
node = this.#rotate(node);
// 返回子树的根结点
return node;
}
@@ -1571,13 +1571,13 @@ AVL 树的独特之处在于「旋转 Rotation」的操作其可 **在不影
=== "Python"
```python title="avl_tree.py"
""" 删除结点 """
def remove(self, val: int):
""" 删除结点 """
root = self.__remove_helper(self.root, val)
return root
""" 递归删除结点(辅助方法) """
def __remove_helper(self, node: Optional[TreeNode], val: int) -> Optional[TreeNode]:
""" 递归删除结点(辅助方法) """
if node is None:
return None
# 1. 查找结点,并删除之
@@ -1603,8 +1603,8 @@ AVL 树的独特之处在于「旋转 Rotation」的操作其可 **在不影
# 2. 执行旋转操作,使该子树重新恢复平衡
return self.__rotate(node)
""" 获取中序遍历中的下一个结点(仅适用于 root 有左子结点的情况) """
def __get_inorder_next(self, node: Optional[TreeNode]) -> Optional[TreeNode]:
""" 获取中序遍历中的下一个结点(仅适用于 root 有左子结点的情况) """
if node is None:
return None
# 循环访问左子结点,直到叶结点时为最小结点,跳出
@@ -1678,16 +1678,16 @@ AVL 树的独特之处在于「旋转 Rotation」的操作其可 **在不影
```javascript title="avl_tree.js"
/* 删除结点 */
remove(val) {
this.root = this.removeHelper(this.root, val);
this.root = this.#removeHelper(this.root, val);
return this.root;
}
/* 递归删除结点(辅助方法) */
removeHelper(node, val) {
#removeHelper(node, val) {
if (node === null) return null;
/* 1. 查找结点,并删除之 */
if (val < node.val) node.left = this.removeHelper(node.left, val);
else if (val > node.val) node.right = this.removeHelper(node.right, val);
if (val < node.val) node.left = this.#removeHelper(node.left, val);
else if (val > node.val) node.right = this.#removeHelper(node.right, val);
else {
if (node.left === null || node.right === null) {
const child = node.left !== null ? node.left : node.right;
@@ -1697,20 +1697,20 @@ AVL 树的独特之处在于「旋转 Rotation」的操作其可 **在不影
else node = child;
} else {
// 子结点数量 = 2 ,则将中序遍历的下个结点删除,并用该结点替换当前结点
const temp = this.getInOrderNext(node.right);
node.right = this.removeHelper(node.right, temp.val);
const temp = this.#getInOrderNext(node.right);
node.right = this.#removeHelper(node.right, temp.val);
node.val = temp.val;
}
}
this.updateHeight(node); // 更新结点高度
this.#updateHeight(node); // 更新结点高度
/* 2. 执行旋转操作,使该子树重新恢复平衡 */
node = this.rotate(node);
node = this.#rotate(node);
// 返回子树的根结点
return node;
}
/* 获取中序遍历中的下一个结点(仅适用于 root 有左子结点的情况) */
getInOrderNext(node) {
#getInOrderNext(node) {
if (node === null) return node;
// 循环访问左子结点,直到叶结点时为最小结点,跳出
while (node.left !== null) {
@@ -1745,7 +1745,7 @@ AVL 树的独特之处在于「旋转 Rotation」的操作其可 **在不影
return null;
} else {
// 子结点数量 = 1 ,直接删除 node
node = child;
node = child;
}
} else {
// 子结点数量 = 2 ,则将中序遍历的下个结点删除,并用该结点替换当前结点

View File

@@ -80,8 +80,8 @@ comments: true
=== "Python"
```python title="binary_search_tree.py"
""" 查找结点 """
def search(self, num: int) -> Optional[TreeNode]:
""" 查找结点 """
cur = self.root
# 循环查找,越过叶结点后跳出
while cur is not None:
@@ -308,8 +308,8 @@ comments: true
=== "Python"
```python title="binary_search_tree.py"
""" 插入结点 """
def insert(self, num: int) -> Optional[TreeNode]:
""" 插入结点 """
root = self.root
# 若树为空,直接提前返回
if root is None:
@@ -392,7 +392,7 @@ comments: true
else cur = cur.left;
}
// 插入结点 val
let node = new Tree.TreeNode(num);
let node = new TreeNode(num);
if (pre.val < num) pre.right = node;
else pre.left = node;
return node;
@@ -692,8 +692,8 @@ comments: true
=== "Python"
```python title="binary_search_tree.py"
""" 删除结点 """
def remove(self, num: int) -> Optional[TreeNode]:
""" 删除结点 """
root = self.root
# 若树为空,直接提前返回
if root is None:
@@ -734,8 +734,8 @@ comments: true
cur.val = tmp
return cur
""" 获取中序遍历中的下一个结点(仅适用于 root 有左子结点的情况) """
def get_inorder_next(self, root: Optional[TreeNode]) -> Optional[TreeNode]:
""" 获取中序遍历中的下一个结点(仅适用于 root 有左子结点的情况) """
if root is None:
return root
# 循环访问左子结点,直到叶结点时为最小结点,跳出

View File

@@ -69,8 +69,8 @@ comments: true
=== "Python"
```python title="binary_tree_bfs.py"
""" 层序遍历 """
def level_order(root: Optional[TreeNode]):
""" 层序遍历 """
# 初始化队列,加入根结点
queue = collections.deque()
queue.append(root)
@@ -120,9 +120,9 @@ comments: true
/* 层序遍历 */
function levelOrder(root) {
// 初始化队列,加入根结点
let queue = [root];
const queue = [root];
// 初始化一个列表,用于保存遍历序列
let list = [];
const list = [];
while (queue.length) {
let node = queue.shift(); // 队列出队
list.push(node.val); // 保存结点值
@@ -337,8 +337,8 @@ comments: true
=== "Python"
```python title="binary_tree_dfs.py"
""" 前序遍历 """
def pre_order(root: Optional[TreeNode]):
""" 前序遍历 """
if root is None:
return
# 访问优先级:根结点 -> 左子树 -> 右子树
@@ -346,8 +346,8 @@ comments: true
pre_order(root=root.left)
pre_order(root=root.right)
""" 中序遍历 """
def in_order(root: Optional[TreeNode]):
""" 中序遍历 """
if root is None:
return
# 访问优先级:左子树 -> 根结点 -> 右子树
@@ -355,8 +355,8 @@ comments: true
res.append(root.val)
in_order(root=root.right)
""" 后序遍历 """
def post_order(root: Optional[TreeNode]):
""" 后序遍历 """
if root is None:
return
# 访问优先级:左子树 -> 右子树 -> 根结点