mirror of
https://github.com/krahets/hello-algo.git
synced 2025-11-02 12:58:42 +08:00
Update the book based on the revised second edition (#1014)
* Revised the book * Update the book with the second revised edition * Revise base on the manuscript of the first edition
This commit is contained in:
@ -25,7 +25,7 @@ class MyList:
|
||||
|
||||
def get(self, index: int) -> int:
|
||||
"""访问元素"""
|
||||
# 索引如果越界则抛出异常,下同
|
||||
# 索引如果越界,则抛出异常,下同
|
||||
if index < 0 or index >= self._size:
|
||||
raise IndexError("索引越界")
|
||||
return self._arr[index]
|
||||
@ -68,12 +68,12 @@ class MyList:
|
||||
self._arr[j] = self._arr[j + 1]
|
||||
# 更新元素数量
|
||||
self._size -= 1
|
||||
# 返回被删除元素
|
||||
# 返回被删除的元素
|
||||
return num
|
||||
|
||||
def extend_capacity(self):
|
||||
"""列表扩容"""
|
||||
# 新建一个长度为原数组 __extend_ratio 倍的新数组,并将原数组拷贝到新数组
|
||||
# 新建一个长度为原数组 _extend_ratio 倍的新数组,并将原数组复制到新数组
|
||||
self._arr = self._arr + [0] * self.capacity() * (self._extend_ratio - 1)
|
||||
# 更新列表容量
|
||||
self._capacity = len(self._arr)
|
||||
|
||||
@ -21,10 +21,10 @@ def backtrack(
|
||||
return
|
||||
# 遍历所有列
|
||||
for col in range(n):
|
||||
# 计算该格子对应的主对角线和副对角线
|
||||
# 计算该格子对应的主对角线和次对角线
|
||||
diag1 = row - col + n - 1
|
||||
diag2 = row + col
|
||||
# 剪枝:不允许该格子所在列、主对角线、副对角线上存在皇后
|
||||
# 剪枝:不允许该格子所在列、主对角线、次对角线上存在皇后
|
||||
if not cols[col] and not diags1[diag1] and not diags2[diag2]:
|
||||
# 尝试:将皇后放置在该格子
|
||||
state[row][col] = "Q"
|
||||
@ -42,7 +42,7 @@ def n_queens(n: int) -> list[list[list[str]]]:
|
||||
state = [["#" for _ in range(n)] for _ in range(n)]
|
||||
cols = [False] * n # 记录列是否有皇后
|
||||
diags1 = [False] * (2 * n - 1) # 记录主对角线上是否有皇后
|
||||
diags2 = [False] * (2 * n - 1) # 记录副对角线上是否有皇后
|
||||
diags2 = [False] * (2 * n - 1) # 记录次对角线上是否有皇后
|
||||
res = []
|
||||
backtrack(0, n, state, res, cols, diags1, diags2)
|
||||
|
||||
|
||||
@ -14,7 +14,7 @@ from graph_adjacency_list import GraphAdjList
|
||||
|
||||
|
||||
def graph_bfs(graph: GraphAdjList, start_vet: Vertex) -> list[Vertex]:
|
||||
"""广度优先遍历 BFS"""
|
||||
"""广度优先遍历"""
|
||||
# 使用邻接表来表示图,以便获取指定顶点的所有邻接顶点
|
||||
# 顶点遍历序列
|
||||
res = []
|
||||
@ -58,7 +58,7 @@ if __name__ == "__main__":
|
||||
print("\n初始化后,图为")
|
||||
graph.print()
|
||||
|
||||
# 广度优先遍历 BFS
|
||||
# 广度优先遍历
|
||||
res = graph_bfs(graph, v[0])
|
||||
print("\n广度优先遍历(BFS)顶点序列为")
|
||||
print(vets_to_vals(res))
|
||||
|
||||
@ -13,7 +13,7 @@ from graph_adjacency_list import GraphAdjList
|
||||
|
||||
|
||||
def dfs(graph: GraphAdjList, visited: set[Vertex], res: list[Vertex], vet: Vertex):
|
||||
"""深度优先遍历 DFS 辅助函数"""
|
||||
"""深度优先遍历辅助函数"""
|
||||
res.append(vet) # 记录访问顶点
|
||||
visited.add(vet) # 标记该顶点已被访问
|
||||
# 遍历该顶点的所有邻接顶点
|
||||
@ -25,7 +25,7 @@ def dfs(graph: GraphAdjList, visited: set[Vertex], res: list[Vertex], vet: Verte
|
||||
|
||||
|
||||
def graph_dfs(graph: GraphAdjList, start_vet: Vertex) -> list[Vertex]:
|
||||
"""深度优先遍历 DFS"""
|
||||
"""深度优先遍历"""
|
||||
# 使用邻接表来表示图,以便获取指定顶点的所有邻接顶点
|
||||
# 顶点遍历序列
|
||||
res = []
|
||||
@ -51,7 +51,7 @@ if __name__ == "__main__":
|
||||
print("\n初始化后,图为")
|
||||
graph.print()
|
||||
|
||||
# 深度优先遍历 DFS
|
||||
# 深度优先遍历
|
||||
res = graph_dfs(graph, v[0])
|
||||
print("\n深度优先遍历(DFS)顶点序列为")
|
||||
print(vets_to_vals(res))
|
||||
|
||||
@ -7,7 +7,7 @@ Author: Krahets (krahets@163.com)
|
||||
|
||||
def max_capacity(ht: list[int]) -> int:
|
||||
"""最大容量:贪心"""
|
||||
# 初始化 i, j 分列数组两端
|
||||
# 初始化 i, j,使其分列数组两端
|
||||
i, j = 0, len(ht) - 1
|
||||
# 初始最大容量为 0
|
||||
res = 0
|
||||
|
||||
@ -93,7 +93,7 @@ if __name__ == "__main__":
|
||||
hmap.print()
|
||||
|
||||
# 查询操作
|
||||
# 向哈希表输入键 key ,得到值 value
|
||||
# 向哈希表中输入键 key ,得到值 value
|
||||
name = hmap.get(15937)
|
||||
print("\n输入学号 15937 ,查询到姓名 " + name)
|
||||
|
||||
|
||||
@ -26,7 +26,7 @@ if __name__ == "__main__":
|
||||
print_dict(hmap)
|
||||
|
||||
# 查询操作
|
||||
# 向哈希表输入键 key ,得到值 value
|
||||
# 向哈希表中输入键 key ,得到值 value
|
||||
name: str = hmap[15937]
|
||||
print("\n输入学号 15937 ,查询到姓名 " + name)
|
||||
|
||||
|
||||
@ -34,11 +34,11 @@ class HashMapChaining:
|
||||
"""查询操作"""
|
||||
index = self.hash_func(key)
|
||||
bucket = self.buckets[index]
|
||||
# 遍历桶,若找到 key 则返回对应 val
|
||||
# 遍历桶,若找到 key ,则返回对应 val
|
||||
for pair in bucket:
|
||||
if pair.key == key:
|
||||
return pair.val
|
||||
# 若未找到 key 则返回 None
|
||||
# 若未找到 key ,则返回 None
|
||||
return None
|
||||
|
||||
def put(self, key: int, val: str):
|
||||
@ -107,7 +107,7 @@ if __name__ == "__main__":
|
||||
hashmap.print()
|
||||
|
||||
# 查询操作
|
||||
# 向哈希表输入键 key ,得到值 value
|
||||
# 向哈希表中输入键 key ,得到值 value
|
||||
name = hashmap.get(13276)
|
||||
print("\n输入学号 13276 ,查询到姓名 " + name)
|
||||
|
||||
|
||||
@ -37,9 +37,9 @@ class HashMapOpenAddressing:
|
||||
first_tombstone = -1
|
||||
# 线性探测,当遇到空桶时跳出
|
||||
while self.buckets[index] is not None:
|
||||
# 若遇到 key ,返回对应桶索引
|
||||
# 若遇到 key ,返回对应的桶索引
|
||||
if self.buckets[index].key == key:
|
||||
# 若之前遇到了删除标记,则将键值对移动至该索引
|
||||
# 若之前遇到了删除标记,则将键值对移动至该索引处
|
||||
if first_tombstone != -1:
|
||||
self.buckets[first_tombstone] = self.buckets[index]
|
||||
self.buckets[index] = self.TOMBSTONE
|
||||
@ -48,7 +48,7 @@ class HashMapOpenAddressing:
|
||||
# 记录遇到的首个删除标记
|
||||
if first_tombstone == -1 and self.buckets[index] is self.TOMBSTONE:
|
||||
first_tombstone = index
|
||||
# 计算桶索引,越过尾部返回头部
|
||||
# 计算桶索引,越过尾部则返回头部
|
||||
index = (index + 1) % self.capacity
|
||||
# 若 key 不存在,则返回添加点的索引
|
||||
return index if first_tombstone == -1 else first_tombstone
|
||||
@ -127,7 +127,7 @@ if __name__ == "__main__":
|
||||
hashmap.print()
|
||||
|
||||
# 查询操作
|
||||
# 向哈希表输入键 key ,得到值 val
|
||||
# 向哈希表中输入键 key ,得到值 val
|
||||
name = hashmap.get(13276)
|
||||
print("\n输入学号 13276 ,查询到姓名 " + name)
|
||||
|
||||
|
||||
@ -23,15 +23,15 @@ class MaxHeap:
|
||||
self.sift_down(i)
|
||||
|
||||
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 # 向下整除
|
||||
|
||||
def swap(self, i: int, j: int):
|
||||
|
||||
@ -30,7 +30,7 @@ def bubble_sort_with_flag(nums: list[int]):
|
||||
nums[j], nums[j + 1] = nums[j + 1], nums[j]
|
||||
flag = True # 记录交换元素
|
||||
if not flag:
|
||||
break # 此轮冒泡未交换任何元素,直接跳出
|
||||
break # 此轮“冒泡”未交换任何元素,直接跳出
|
||||
|
||||
|
||||
"""Driver Code"""
|
||||
|
||||
@ -7,12 +7,12 @@ Author: timi (xisunyy@163.com), Krahets (krahets@163.com)
|
||||
|
||||
def merge(nums: list[int], left: int, mid: int, right: int):
|
||||
"""合并左子数组和右子数组"""
|
||||
# 左子数组区间 [left, mid], 右子数组区间 [mid+1, right]
|
||||
# 左子数组区间为 [left, mid], 右子数组区间为 [mid+1, right]
|
||||
# 创建一个临时数组 tmp ,用于存放合并后的结果
|
||||
tmp = [0] * (right - left + 1)
|
||||
# 初始化左子数组和右子数组的起始索引
|
||||
i, j, k = left, mid + 1, 0
|
||||
# 当左右子数组都还有元素时,比较并将较小的元素复制到临时数组中
|
||||
# 当左右子数组都还有元素时,进行比较并将较小的元素复制到临时数组中
|
||||
while i <= mid and j <= right:
|
||||
if nums[i] <= nums[j]:
|
||||
tmp[k] = nums[i]
|
||||
|
||||
@ -39,7 +39,7 @@ class QuickSortMedian:
|
||||
"""快速排序类(中位基准数优化)"""
|
||||
|
||||
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]):
|
||||
|
||||
@ -39,7 +39,7 @@ class ArrayDeque:
|
||||
print("双向队列已满")
|
||||
return
|
||||
# 队首指针向左移动一位
|
||||
# 通过取余操作,实现 front 越过数组头部后回到尾部
|
||||
# 通过取余操作实现 front 越过数组头部后回到尾部
|
||||
self._front = self.index(self._front - 1)
|
||||
# 将 num 添加至队首
|
||||
self._nums[self._front] = num
|
||||
@ -50,7 +50,7 @@ class ArrayDeque:
|
||||
if self._size == self.capacity():
|
||||
print("双向队列已满")
|
||||
return
|
||||
# 计算尾指针,指向队尾索引 + 1
|
||||
# 计算队尾指针,指向队尾索引 + 1
|
||||
rear = self.index(self._front + self._size)
|
||||
# 将 num 添加至队尾
|
||||
self._nums[rear] = num
|
||||
|
||||
@ -30,8 +30,8 @@ class ArrayQueue:
|
||||
"""入队"""
|
||||
if self._size == self.capacity():
|
||||
raise IndexError("队列已满")
|
||||
# 计算尾指针,指向队尾索引 + 1
|
||||
# 通过取余操作,实现 rear 越过数组尾部后回到头部
|
||||
# 计算队尾指针,指向队尾索引 + 1
|
||||
# 通过取余操作实现 rear 越过数组尾部后回到头部
|
||||
rear: int = (self._front + self._size) % self.capacity()
|
||||
# 将 num 添加至队尾
|
||||
self._nums[rear] = num
|
||||
@ -40,7 +40,7 @@ class ArrayQueue:
|
||||
def pop(self) -> int:
|
||||
"""出队"""
|
||||
num: int = self.peek()
|
||||
# 队首指针向后移动一位,若越过尾部则返回到数组头部
|
||||
# 队首指针向后移动一位,若越过尾部,则返回到数组头部
|
||||
self._front = (self._front + 1) % self.capacity()
|
||||
self._size -= 1
|
||||
return num
|
||||
|
||||
@ -30,7 +30,7 @@ class LinkedListQueue:
|
||||
|
||||
def push(self, num: int):
|
||||
"""入队"""
|
||||
# 尾节点后添加 num
|
||||
# 在尾节点后添加 num
|
||||
node = ListNode(num)
|
||||
# 如果队列为空,则令头、尾节点都指向该节点
|
||||
if self._front is None:
|
||||
|
||||
@ -101,7 +101,7 @@ class AVLTree:
|
||||
"""递归插入节点(辅助方法)"""
|
||||
if node is None:
|
||||
return TreeNode(val)
|
||||
# 1. 查找插入位置,并插入节点
|
||||
# 1. 查找插入位置并插入节点
|
||||
if val < node.val:
|
||||
node.left = self.insert_helper(node.left, val)
|
||||
elif val > node.val:
|
||||
@ -122,7 +122,7 @@ class AVLTree:
|
||||
"""递归删除节点(辅助方法)"""
|
||||
if node is None:
|
||||
return None
|
||||
# 1. 查找节点,并删除之
|
||||
# 1. 查找节点并删除
|
||||
if val < node.val:
|
||||
node.left = self.remove_helper(node.left, val)
|
||||
elif val > node.val:
|
||||
|
||||
Reference in New Issue
Block a user