This commit is contained in:
krahets 2023-05-22 22:01:18 +08:00
parent 29807a3761
commit be77ba7a70
16 changed files with 60 additions and 58 deletions

View file

@ -434,12 +434,12 @@ comments: true
```python title="list.py" ```python title="list.py"
# 通过索引遍历列表 # 通过索引遍历列表
count: int = 0 count = 0
for i in range(len(list)): for i in range(len(list)):
count += 1 count += 1
# 直接遍历列表元素 # 直接遍历列表元素
count: int = 0 count = 0
for n in list: for n in list:
count += 1 count += 1
``` ```

View file

@ -976,7 +976,9 @@ comments: true
"""恢复状态""" """恢复状态"""
state.pop() state.pop()
def backtrack(state: list[TreeNode], choices: list[TreeNode], res: list[list[TreeNode]]): def backtrack(
state: list[TreeNode], choices: list[TreeNode], res: list[list[TreeNode]]
):
"""回溯算法:例题三""" """回溯算法:例题三"""
# 检查是否为解 # 检查是否为解
if is_solution(state): if is_solution(state):

View file

@ -93,10 +93,10 @@ comments: true
return 0 return 0
def algorithm(n) -> int: # 输入数据 def algorithm(n) -> int: # 输入数据
A: int = 0 # 暂存数据(常量,一般用大写字母表示) A = 0 # 暂存数据(常量,一般用大写字母表示)
b: int = 0 # 暂存数据(变量) b = 0 # 暂存数据(变量)
node = Node(0) # 暂存数据(对象) node = Node(0) # 暂存数据(对象)
c: int = function() # 栈帧空间(调用函数) c = function() # 栈帧空间(调用函数)
return A + b + c # 输出数据 return A + b + c # 输出数据
``` ```
@ -299,10 +299,10 @@ comments: true
```python title="" ```python title=""
def algorithm(n: int) -> None: def algorithm(n: int) -> None:
a: int = 0 # O(1) a = 0 # O(1)
b: List[int] = [0] * 10000 # O(1) b = [0] * 10000 # O(1)
if n > 10: if n > 10:
nums: List[int] = [0] * n # O(n) nums = [0] * n # O(n)
``` ```
=== "Go" === "Go"
@ -658,12 +658,12 @@ $$
def constant(n: int) -> None: def constant(n: int) -> None:
"""常数阶""" """常数阶"""
# 常量、变量、对象占用 O(1) 空间 # 常量、变量、对象占用 O(1) 空间
a: int = 0 a = 0
nums: list[int] = [0] * 10000 nums = [0] * 10000
node = ListNode(0) node = ListNode(0)
# 循环中的变量占用 O(1) 空间 # 循环中的变量占用 O(1) 空间
for _ in range(n): for _ in range(n):
c: int = 0 c = 0
# 循环中的函数占用 O(1) 空间 # 循环中的函数占用 O(1) 空间
for _ in range(n): for _ in range(n):
function() function()
@ -876,7 +876,7 @@ $$
def linear(n: int) -> None: def linear(n: int) -> None:
"""线性阶""" """线性阶"""
# 长度为 n 的列表占用 O(n) 空间 # 长度为 n 的列表占用 O(n) 空间
nums: list[int] = [0] * n nums = [0] * n
# 长度为 n 的哈希表占用 O(n) 空间 # 长度为 n 的哈希表占用 O(n) 空间
mapp = dict[int, str]() mapp = dict[int, str]()
for i in range(n): for i in range(n):
@ -1220,7 +1220,7 @@ $$
def quadratic(n: int) -> None: def quadratic(n: int) -> None:
"""平方阶""" """平方阶"""
# 二维列表占用 O(n^2) 空间 # 二维列表占用 O(n^2) 空间
num_matrix: list[list[int]] = [[0] * n for _ in range(n)] num_matrix = [[0] * n for _ in range(n)]
``` ```
=== "Go" === "Go"
@ -1388,7 +1388,7 @@ $$
if n <= 0: if n <= 0:
return 0 return 0
# 数组 nums 长度为 n, n-1, ..., 2, 1 # 数组 nums 长度为 n, n-1, ..., 2, 1
nums: list[int] = [0] * n nums = [0] * n
return quadratic_recur(n - 1) return quadratic_recur(n - 1)
``` ```

View file

@ -421,7 +421,7 @@ $$
```python title="" ```python title=""
def algorithm(n: int) -> None: def algorithm(n: int) -> None:
a: int = 1 # +1 a = 1 # +1
a = a + 1 # +1 a = a + 1 # +1
a = a * 2 # +1 a = a * 2 # +1
# 循环 n 次 # 循环 n 次
@ -612,7 +612,7 @@ $$
```python title="" ```python title=""
def algorithm(n: int) -> None: def algorithm(n: int) -> None:
a: int = 1 # +0技巧 1 a = 1 # +0技巧 1
a = a + n # +0技巧 1 a = a + n # +0技巧 1
# +n技巧 2 # +n技巧 2
for i in range(5 * n + 1): for i in range(5 * n + 1):
@ -821,8 +821,8 @@ $$
```python title="time_complexity.py" ```python title="time_complexity.py"
def constant(n: int) -> int: def constant(n: int) -> int:
"""常数阶""" """常数阶"""
count: int = 0 count = 0
size: int = 100000 size = 100000
for _ in range(size): for _ in range(size):
count += 1 count += 1
return count return count
@ -957,7 +957,7 @@ $$
```python title="time_complexity.py" ```python title="time_complexity.py"
def linear(n: int) -> int: def linear(n: int) -> int:
"""线性阶""" """线性阶"""
count: int = 0 count = 0
for _ in range(n): for _ in range(n):
count += 1 count += 1
return count return count
@ -1089,7 +1089,7 @@ $$
```python title="time_complexity.py" ```python title="time_complexity.py"
def array_traversal(nums: list[int]) -> int: def array_traversal(nums: list[int]) -> int:
"""线性阶(遍历数组)""" """线性阶(遍历数组)"""
count: int = 0 count = 0
# 循环次数与数组长度成正比 # 循环次数与数组长度成正比
for num in nums: for num in nums:
count += 1 count += 1
@ -1235,7 +1235,7 @@ $$
```python title="time_complexity.py" ```python title="time_complexity.py"
def quadratic(n: int) -> int: def quadratic(n: int) -> int:
"""平方阶""" """平方阶"""
count: int = 0 count = 0
# 循环次数与数组长度成平方关系 # 循环次数与数组长度成平方关系
for i in range(n): for i in range(n):
for j in range(n): for j in range(n):
@ -1418,7 +1418,7 @@ $$
```python title="time_complexity.py" ```python title="time_complexity.py"
def bubble_sort(nums: list[int]) -> int: def bubble_sort(nums: list[int]) -> int:
"""平方阶(冒泡排序)""" """平方阶(冒泡排序)"""
count: int = 0 # 计数器 count = 0 # 计数器
# 外循环:待排序元素数量为 n-1, n-2, ..., 1 # 外循环:待排序元素数量为 n-1, n-2, ..., 1
for i in range(len(nums) - 1, 0, -1): for i in range(len(nums) - 1, 0, -1):
# 内循环:冒泡操作 # 内循环:冒泡操作
@ -1644,8 +1644,8 @@ $$
```python title="time_complexity.py" ```python title="time_complexity.py"
def exponential(n: int) -> int: def exponential(n: int) -> int:
"""指数阶(循环实现)""" """指数阶(循环实现)"""
count: int = 0 count = 0
base: int = 1 base = 1
# cell 每轮一分为二,形成数列 1, 2, 4, 8, ..., 2^(n-1) # cell 每轮一分为二,形成数列 1, 2, 4, 8, ..., 2^(n-1)
for _ in range(n): for _ in range(n):
for _ in range(base): for _ in range(base):
@ -1942,7 +1942,7 @@ $$
```python title="time_complexity.py" ```python title="time_complexity.py"
def logarithmic(n: float) -> int: def logarithmic(n: float) -> int:
"""对数阶(循环实现)""" """对数阶(循环实现)"""
count: int = 0 count = 0
while n > 1: while n > 1:
n = n / 2 n = n / 2
count += 1 count += 1
@ -2373,7 +2373,7 @@ $$
"""阶乘阶(递归实现)""" """阶乘阶(递归实现)"""
if n == 0: if n == 0:
return 1 return 1
count: int = 0 count = 0
# 从 1 个分裂出 n 个 # 从 1 个分裂出 n 个
for _ in range(n): for _ in range(n):
count += factorial_recur(n - 1) count += factorial_recur(n - 1)
@ -2570,7 +2570,7 @@ $$
def random_numbers(n: int) -> list[int]: def random_numbers(n: int) -> list[int]:
"""生成一个数组,元素为: 1, 2, ..., n ,顺序被打乱""" """生成一个数组,元素为: 1, 2, ..., n ,顺序被打乱"""
# 生成数组 nums =: 1, 2, 3, ..., n # 生成数组 nums =: 1, 2, 3, ..., n
nums: list[int] = [i for i in range(1, n + 1)] nums = [i for i in range(1, n + 1)]
# 随机打乱数组元素 # 随机打乱数组元素
random.shuffle(nums) random.shuffle(nums)
return nums return nums

View file

@ -26,7 +26,7 @@ comments: true
随着计算机的蓬勃发展,字符集与编码标准百花齐放,而这带来了许多问题。一方面,这些字符集一般只定义了特定语言的字符,无法在多语言环境下正常工作;另一方面,同一种语言也存在多种字符集标准,如果两台电脑安装的是不同的编码标准,则在信息传递时就会出现乱码。 随着计算机的蓬勃发展,字符集与编码标准百花齐放,而这带来了许多问题。一方面,这些字符集一般只定义了特定语言的字符,无法在多语言环境下正常工作;另一方面,同一种语言也存在多种字符集标准,如果两台电脑安装的是不同的编码标准,则在信息传递时就会出现乱码。
那个时代的人们就在想:如果推出一个足够完整的字符集,将世界范围内的所有语言和符号都纳入其中,不就可以解决跨语言环境和乱码问题了吗?在这种想法的驱动下,一个大而全的字符集 Unicode 应运而生。 那个时代的人们就在想:**如果推出一个足够完整的字符集,将世界范围内的所有语言和符号都收录其中,不就可以解决跨语言环境和乱码问题了吗**?在这种想法的驱动下,一个大而全的字符集 Unicode 应运而生。
「Unicode」的全称为“统一字符编码”理论上能容纳一百多万个字符。它致力于将全球范围内的字符纳入到统一的字符集之中提供一种通用的字符集来处理和显示各种语言文字减少因为编码标准不同而产生的乱码问题。 「Unicode」的全称为“统一字符编码”理论上能容纳一百多万个字符。它致力于将全球范围内的字符纳入到统一的字符集之中提供一种通用的字符集来处理和显示各种语言文字减少因为编码标准不同而产生的乱码问题。
@ -48,7 +48,7 @@ Unicode 是一种字符集标准,本质上是给每个字符分配一个编号
UTF-8 的编码规则并不复杂,分为两种情况: UTF-8 的编码规则并不复杂,分为两种情况:
- **长度为 1 字节的字符**:将最高位设置为 0 、其余 7 位设置为 Unicode 码点。值得注意的是ASCII 字符在 Unicode 字符集中占据了前 128 个码点。也就是说,**UTF-8 编码可以向下兼容 ASCII 码**。这意味着我们可以使用 UTF-8 来解析年代久远的 ASCII 码文本。 - 对于长度为 1 字节的字符,将最高位设置为 $0$ 、其余 7 位设置为 Unicode 码点。值得注意的是ASCII 字符在 Unicode 字符集中占据了前 128 个码点。也就是说,**UTF-8 编码可以向下兼容 ASCII 码**。这意味着我们可以使用 UTF-8 来解析年代久远的 ASCII 码文本。
- 对于长度为 $n$ 字节的字符(其中 $n > 1$),将首个字节的高 $n$ 位都设置为 $1$ 、第 $n + 1$ 位设置为 $0$ ;从第二个字节开始,将每个字节的高 2 位都设置为 $10$ ;其余所有位用于填充字符的 Unicode 码点。 - 对于长度为 $n$ 字节的字符(其中 $n > 1$),将首个字节的高 $n$ 位都设置为 $1$ 、第 $n + 1$ 位设置为 $0$ ;从第二个字节开始,将每个字节的高 2 位都设置为 $10$ ;其余所有位用于填充字符的 Unicode 码点。
下图展示了“Hello算法”对应的 UTF-8 编码。将最高 $n$ 位设置为 $1$ 比较容易理解,可以向系统指出字符的长度为 $n$ 。那么,为什么要将其余所有字节的高 2 位都设置为 $10$ 呢?实际上,这个 $10$ 能够起到校验符的作用,因为在 UTF-8 编码规则下,不可能有字符的最高两位是 $10$ 。这是因为长度为 1 字节的字符的最高一位是 $0$ 。假设系统从一个错误的字节开始解析文本,字节头部的 $10$ 能够帮助系统快速的判断出异常。 下图展示了“Hello算法”对应的 UTF-8 编码。将最高 $n$ 位设置为 $1$ 比较容易理解,可以向系统指出字符的长度为 $n$ 。那么,为什么要将其余所有字节的高 2 位都设置为 $10$ 呢?实际上,这个 $10$ 能够起到校验符的作用,因为在 UTF-8 编码规则下,不可能有字符的最高两位是 $10$ 。这是因为长度为 1 字节的字符的最高一位是 $0$ 。假设系统从一个错误的字节开始解析文本,字节头部的 $10$ 能够帮助系统快速的判断出异常。

View file

@ -631,7 +631,7 @@ $$
def hash_func(self, key: int) -> int: def hash_func(self, key: int) -> int:
"""哈希函数""" """哈希函数"""
index: int = key % 100 index = key % 100
return index return index
def get(self, key: int) -> str: def get(self, key: int) -> str:
@ -664,7 +664,7 @@ $$
def key_set(self) -> list[int]: def key_set(self) -> list[int]:
"""获取所有键""" """获取所有键"""
result: list[int] = [] result = []
for pair in self.buckets: for pair in self.buckets:
if pair is not None: if pair is not None:
result.append(pair.key) result.append(pair.key)
@ -672,7 +672,7 @@ $$
def value_set(self) -> list[str]: def value_set(self) -> list[str]:
"""获取所有值""" """获取所有值"""
result: list[str] = [] result = []
for pair in self.buckets: for pair in self.buckets:
if pair is not None: if pair is not None:
result.append(pair.val) result.append(pair.val)

View file

@ -4,7 +4,7 @@ comments: true
# 10.2. &nbsp; 二分查找边界 # 10.2. &nbsp; 二分查找边界
上一节规定目标元素在数组中是唯一的。如果目标元素在数组中多次出现,上节介绍的方法只能保证返回其中一个目标元素的索引,**而无法确定该索引的左边和右边还有多少目标元素**。 上一节中,题目规定数组中所有元素都是唯一的。如果目标元素在数组中多次出现,上节介绍的方法只能保证返回其中一个目标元素的索引,**而无法确定该索引的左边和右边还有多少目标元素**。
!!! question !!! question

View file

@ -6,7 +6,7 @@ comments: true
「搜索算法 Searching Algorithm」用于在数据结构例如数组、链表、树或图中搜索一个或一组满足特定条件的元素。 「搜索算法 Searching Algorithm」用于在数据结构例如数组、链表、树或图中搜索一个或一组满足特定条件的元素。
我们已经学过数组、链表、树和图的遍历方法,也学过哈希表、二叉搜索树等可用于实现查询的复杂数据结构。因此,搜索算法对于我们来说并不陌生。在本节,我们将从更加系统的视角切入,重新审视搜索算法。 在前面的章节中,我们已经学习了数组、链表、树和图的遍历方法,也了解过哈希表和二叉搜索树等具有查询功能的复杂数据结构。因此,搜索算法对于我们来说并不陌生。在本节,我们将从更加系统的视角切入,重新审视搜索算法。
## 10.4.1. &nbsp; 暴力搜索 ## 10.4.1. &nbsp; 暴力搜索

View file

@ -87,7 +87,7 @@ comments: true
```python title="bubble_sort.py" ```python title="bubble_sort.py"
def bubble_sort(nums: list[int]) -> None: def bubble_sort(nums: list[int]) -> None:
"""冒泡排序""" """冒泡排序"""
n: int = len(nums) n = len(nums)
# 外循环:待排序元素数量为 n-1, n-2, ..., 1 # 外循环:待排序元素数量为 n-1, n-2, ..., 1
for i in range(n - 1, 0, -1): for i in range(n - 1, 0, -1):
# 内循环:冒泡操作 # 内循环:冒泡操作
@ -302,10 +302,10 @@ comments: true
```python title="bubble_sort.py" ```python title="bubble_sort.py"
def bubble_sort_with_flag(nums: list[int]) -> None: def bubble_sort_with_flag(nums: list[int]) -> None:
"""冒泡排序(标志优化)""" """冒泡排序(标志优化)"""
n: int = len(nums) n = len(nums)
# 外循环:待排序元素数量为 n-1, n-2, ..., 1 # 外循环:待排序元素数量为 n-1, n-2, ..., 1
for i in range(n - 1, 0, -1): for i in range(n - 1, 0, -1):
flag: bool = False # 初始化标志位 flag = False # 初始化标志位
# 内循环:冒泡操作 # 内循环:冒泡操作
for j in range(i): for j in range(i):
if nums[j] > nums[j + 1]: if nums[j] > nums[j + 1]:

View file

@ -67,8 +67,8 @@ comments: true
"""插入排序""" """插入排序"""
# 外循环base = nums[1], nums[2], ..., nums[n-1] # 外循环base = nums[1], nums[2], ..., nums[n-1]
for i in range(1, len(nums)): for i in range(1, len(nums)):
base: int = nums[i] base = nums[i]
j: int = i - 1 j = i - 1
# 内循环:将 base 插入到左边的正确位置 # 内循环:将 base 插入到左边的正确位置
while j >= 0 and nums[j] > base: while j >= 0 and nums[j] > base:
nums[j + 1] = nums[j] # 1. 将 nums[j] 向右移动一位 nums[j + 1] = nums[j] # 1. 将 nums[j] 向右移动一位

View file

@ -151,16 +151,16 @@ comments: true
# 左子数组区间 [left, mid] # 左子数组区间 [left, mid]
# 右子数组区间 [mid + 1, right] # 右子数组区间 [mid + 1, right]
# 初始化辅助数组 # 初始化辅助数组
tmp: list[int] = list(nums[left : right + 1]) tmp = list(nums[left : right + 1])
# 左子数组的起始索引和结束索引 # 左子数组的起始索引和结束索引
left_start: int = 0 left_start = 0
left_end: int = mid - left left_end = mid - left
# 右子数组的起始索引和结束索引 # 右子数组的起始索引和结束索引
right_start: int = mid + 1 - left right_start = mid + 1 - left
right_end: int = right - left right_end = right - left
# i, j 分别指向左子数组、右子数组的首元素 # i, j 分别指向左子数组、右子数组的首元素
i: int = left_start i = left_start
j: int = right_start j = right_start
# 通过覆盖原数组 nums 来合并左子数组和右子数组 # 通过覆盖原数组 nums 来合并左子数组和右子数组
for k in range(left, right + 1): for k in range(left, right + 1):
# 若“左子数组已全部合并完”,则选取右子数组元素,并且 j++ # 若“左子数组已全部合并完”,则选取右子数组元素,并且 j++
@ -182,7 +182,7 @@ comments: true
if left >= right: if left >= right:
return # 当子数组长度为 1 时终止递归 return # 当子数组长度为 1 时终止递归
# 划分阶段 # 划分阶段
mid: int = (left + right) // 2 # 计算中点 mid = (left + right) // 2 # 计算中点
merge_sort(nums, left, mid) # 递归左子数组 merge_sort(nums, left, mid) # 递归左子数组
merge_sort(nums, mid + 1, right) # 递归右子数组 merge_sort(nums, mid + 1, right) # 递归右子数组
# 合并阶段 # 合并阶段

View file

@ -364,7 +364,7 @@ comments: true
if left >= right: if left >= right:
return return
# 哨兵划分 # 哨兵划分
pivot: int = self.partition(nums, left, right) pivot = self.partition(nums, left, right)
# 递归左子数组、右子数组 # 递归左子数组、右子数组
self.quick_sort(nums, left, pivot - 1) self.quick_sort(nums, left, pivot - 1)
self.quick_sort(nums, pivot + 1, right) self.quick_sort(nums, pivot + 1, right)
@ -621,7 +621,7 @@ comments: true
def partition(self, nums: list[int], left: int, right: int) -> int: def partition(self, nums: list[int], left: int, right: int) -> int:
"""哨兵划分(三数取中值)""" """哨兵划分(三数取中值)"""
# 以 nums[left] 作为基准数 # 以 nums[left] 作为基准数
med: int = self.median_three(nums, left, (left + right) // 2, right) med = self.median_three(nums, left, (left + right) // 2, right)
# 将中位数交换至数组最左端 # 将中位数交换至数组最左端
nums[left], nums[med] = nums[med], nums[left] nums[left], nums[med] = nums[med], nums[left]
# 以 nums[left] 作为基准数 # 以 nums[left] 作为基准数
@ -964,7 +964,7 @@ comments: true
# 子数组长度为 1 时终止 # 子数组长度为 1 时终止
while left < right: while left < right:
# 哨兵划分操作 # 哨兵划分操作
pivot: int = self.partition(nums, left, right) pivot = self.partition(nums, left, right)
# 对两个子数组中较短的那个执行快排 # 对两个子数组中较短的那个执行快排
if pivot - left < right - pivot: if pivot - left < right - pivot:
self.quick_sort(nums, left, pivot - 1) # 递归排序左子数组 self.quick_sort(nums, left, pivot - 1) # 递归排序左子数组

View file

@ -691,8 +691,8 @@ comments: true
def to_array(self) -> list[int]: def to_array(self) -> list[int]:
"""返回数组用于打印""" """返回数组用于打印"""
node: ListNode | None = self.front node = self.front
res: list[int] = [0] * self.size() res = [0] * self.size()
for i in range(self.size()): for i in range(self.size()):
res[i] = node.val res[i] = node.val
node = node.next node = node.next

View file

@ -1220,7 +1220,7 @@ comments: true
def to_list(self) -> list[int]: def to_list(self) -> list[int]:
"""返回列表用于打印""" """返回列表用于打印"""
res: list[int] = [0] * self.size() res = [0] * self.size()
j: int = self.__front j: int = self.__front
for i in range(self.size()): for i in range(self.size()):
res[i] = self.__nums[(j % self.capacity())] res[i] = self.__nums[(j % self.capacity())]

View file

@ -447,7 +447,7 @@ comments: true
def to_list(self) -> list[int]: def to_list(self) -> list[int]:
"""转化为列表用于打印""" """转化为列表用于打印"""
arr: list[int] = [] arr = []
node = self.__peek node = self.__peek
while node: while node:
arr.append(node.val) arr.append(node.val)

View file

@ -75,7 +75,7 @@ comments: true
queue: deque[TreeNode] = deque() queue: deque[TreeNode] = deque()
queue.append(root) queue.append(root)
# 初始化一个列表,用于保存遍历序列 # 初始化一个列表,用于保存遍历序列
res: list[int] = [] res = []
while queue: while queue:
node: TreeNode = queue.popleft() # 队列出队 node: TreeNode = queue.popleft() # 队列出队
res.append(node.val) # 保存节点值 res.append(node.val) # 保存节点值