From 24d90931e3b07bbde4fe3b2c01259abd08216728 Mon Sep 17 00:00:00 2001 From: krahets Date: Sun, 21 May 2023 19:58:21 +0800 Subject: [PATCH] Update the callouts for the algorithm problems. --- .../chapter_searching/binary_search_edge.py | 6 ++--- .../binary_search_rotation.py | 24 ------------------- .../backtracking_algorithm.md | 12 +++++++--- docs/chapter_backtracking/n_queens_problem.md | 4 +++- .../permutations_problem.md | 8 +++++-- docs/chapter_searching/binary_search.md | 4 +++- docs/chapter_searching/binary_search_edge.md | 4 +++- .../replace_linear_by_hashing.md | 4 ++-- 8 files changed, 29 insertions(+), 37 deletions(-) delete mode 100644 codes/python/chapter_searching/binary_search_rotation.py diff --git a/codes/python/chapter_searching/binary_search_edge.py b/codes/python/chapter_searching/binary_search_edge.py index c14d8347..b3d48a6a 100644 --- a/codes/python/chapter_searching/binary_search_edge.py +++ b/codes/python/chapter_searching/binary_search_edge.py @@ -12,11 +12,11 @@ def binary_search_left_edge(nums: list[int], target: int) -> int: while i <= j: m = (i + j) // 2 # 计算中点索引 m if nums[m] < target: - i = m + 1 # 此情况说明 target 在区间 [m+1, j] 中 + i = m + 1 # target 在区间 [m+1, j] 中 elif nums[m] > target: - j = m - 1 # 此情况说明 target 在区间 [i, m-1] 中 + j = m - 1 # target 在区间 [i, m-1] 中 else: - j = m - 1 # 此情况说明首个小于 target 的元素在区间 [i, m-1] 中 + j = m - 1 # 首个小于 target 的元素在区间 [i, m-1] 中 if i == len(nums) or nums[i] != target: return -1 # 未找到目标元素,返回 -1 return i diff --git a/codes/python/chapter_searching/binary_search_rotation.py b/codes/python/chapter_searching/binary_search_rotation.py deleted file mode 100644 index 0d47eb6d..00000000 --- a/codes/python/chapter_searching/binary_search_rotation.py +++ /dev/null @@ -1,24 +0,0 @@ - - - -def binary_search_rotation(nums: list[int]) -> int: - """二分查找左边界(双闭区间)""" - # 初始化双闭区间 [0, n-1] ,即 i, j 分别指向数组首元素、尾元素 - i, j = 0, len(nums) - 1 - while True: - m = (i + j) // 2 # 计算中点索引 m - if nums[m] < nums[j]: - j = m # 此情况说明 target 在区间 [m+1, j] 中 - elif nums[m] > nums[j]: - i = m + 1 # 此情况说明 target 在区间 [i, m-1] 中 - else: - return i # 此情况说明 i == j == m ,找到旋转点 - - -"""Driver Code""" -if __name__ == "__main__": - nums: list[int] = [23, 67, 70, 92, 1, 3, 6, 8, 12, 15] - - # 二分查找左边界 - index_left = binary_search_rotation(nums) - print("数组旋转点的索引 = ", index_left) diff --git a/docs/chapter_backtracking/backtracking_algorithm.md b/docs/chapter_backtracking/backtracking_algorithm.md index 35e8c50c..f8e6af07 100644 --- a/docs/chapter_backtracking/backtracking_algorithm.md +++ b/docs/chapter_backtracking/backtracking_algorithm.md @@ -4,7 +4,9 @@ 回溯算法通常采用「深度优先搜索」来遍历解空间。在二叉树章节中,我们提到前序、中序和后序遍历都属于深度优先搜索。下面,我们从二叉树的前序遍历入手,逐步了解回溯算法的工作原理。 -!!! question "例题一:在二叉树中搜索并返回所有值为 $7$ 的节点" +!!! question "例题一" + + 给定一个二叉树,搜索并记录所有值为 $7$ 的节点,返回节点列表。 **解题思路**:前序遍历这颗树,并判断当前节点的值是否为 $7$ ,若是则将该节点的值加入到结果列表 `res` 之中。 @@ -78,7 +80,9 @@ 值得说明的是,**回退并不等价于函数返回**。为解释这一点,我们对例题一稍作拓展。 -!!! question "在二叉树中搜索所有值为 $7$ 的节点,**返回根节点到这些节点的路径**" +!!! question "例题二" + + 在二叉树中搜索所有值为 $7$ 的节点,**返回根节点到这些节点的路径**。 **解题思路**:在例题一代码的基础上,我们需要借助一个列表 `path` 记录访问过的节点路径。当访问到值为 $7$ 的节点时,则复制 `path` 并添加进结果列表 `res` 。遍历完成后,`res` 中保存的就是所有的解。 @@ -181,7 +185,9 @@ 复杂的回溯问题通常包含一个或多个约束条件,**约束条件通常可用于“剪枝”**。 -!!! question "例题三:在二叉树中搜索所有值为 $7$ 的节点,返回根节点到这些节点的路径,**路径中不能包含值为 $3$ 的节点**" +!!! question "例题三" + + 在二叉树中搜索所有值为 $7$ 的节点,返回根节点到这些节点的路径,**路径中不能包含值为 $3$ 的节点**。 **解题思路**:在例题二的基础上添加剪枝操作,当遇到值为 $3$ 的节点时,则终止继续搜索。 diff --git a/docs/chapter_backtracking/n_queens_problem.md b/docs/chapter_backtracking/n_queens_problem.md index 4fca7367..f544b800 100644 --- a/docs/chapter_backtracking/n_queens_problem.md +++ b/docs/chapter_backtracking/n_queens_problem.md @@ -1,6 +1,8 @@ # N 皇后问题 -!!! question "根据国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。给定 $n$ 个皇后和一个 $n \times n$ 大小的棋盘,寻找使得所有皇后之间无法相互攻击的摆放方案。" +!!! question + + 根据国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。给定 $n$ 个皇后和一个 $n \times n$ 大小的棋盘,寻找使得所有皇后之间无法相互攻击的摆放方案。 如下图所示,当 $n = 4$ 时,共可以找到两个解。从回溯算法的角度看,$n \times n$ 大小的棋盘共有 $n^2$ 个格子,给出了所有的选择 `choices` 。在逐个放置皇后的过程中,棋盘状态在不断地变化,每个时刻的棋盘就是状态 `state` 。 diff --git a/docs/chapter_backtracking/permutations_problem.md b/docs/chapter_backtracking/permutations_problem.md index e7db01e6..94e46b7f 100644 --- a/docs/chapter_backtracking/permutations_problem.md +++ b/docs/chapter_backtracking/permutations_problem.md @@ -16,7 +16,9 @@ ## 无重复的情况 -!!! question "输入一个整数数组,数组中不包含重复元素,返回所有可能的排列。" +!!! question + + 输入一个整数数组,数组中不包含重复元素,返回所有可能的排列。 **从回溯算法的角度看,我们可以把生成排列的过程想象成一系列选择的结果**。假设输入数组为 $[1, 2, 3]$ ,如果我们先选择 $1$ 、再选择 $3$ 、最后选择 $2$ ,则获得排列 $[1, 3, 2]$ 。回退表示撤销一个选择,之后继续尝试其他选择。 @@ -116,7 +118,9 @@ ## 考虑重复的情况 -!!! question "输入一个整数数组,**数组中可能包含重复元素**,返回所有不重复的排列。" +!!! question + + 输入一个整数数组,**数组中可能包含重复元素**,返回所有不重复的排列。 假设输入数组为 $[1, 1, 2]$ 。为了方便区分两个重复的元素 $1$ ,接下来我们将第二个元素记为 $\hat{1}$ 。如下图所示,上述方法生成的排列有一半都是重复的。 diff --git a/docs/chapter_searching/binary_search.md b/docs/chapter_searching/binary_search.md index 4a81aa69..9d512c52 100755 --- a/docs/chapter_searching/binary_search.md +++ b/docs/chapter_searching/binary_search.md @@ -4,7 +4,9 @@ 我们先来求解一个简单的二分查找问题。 -!!! question "给定一个长度为 $n$ 的有序数组 `nums` ,元素按从小到大的顺序排列。查找并返回元素 `target` 在该数组中的索引。若数组中不包含该元素,则返回 $-1$ 。数组中不包含重复元素。" +!!! question + + 给定一个长度为 $n$ 的有序数组 `nums` ,元素按从小到大的顺序排列。请查找并返回元素 `target` 在该数组中的索引。若数组中不包含该元素,则返回 $-1$ 。数组中不包含重复元素。 该数组的索引范围可以使用区间 $[0, n - 1]$ 来表示。其中,**中括号表示“闭区间”,即包含边界值本身**。在该表示下,区间 $[i, j]$ 在 $i = j$ 时仍包含一个元素,在 $i > j$ 时为空区间。 diff --git a/docs/chapter_searching/binary_search_edge.md b/docs/chapter_searching/binary_search_edge.md index 69e3da93..9de5d1ce 100644 --- a/docs/chapter_searching/binary_search_edge.md +++ b/docs/chapter_searching/binary_search_edge.md @@ -8,7 +8,9 @@ ## 查找最左一个元素 -!!! question "查找并返回元素 `target` 在有序数组 `nums` 中首次出现的索引。若数组中不包含该元素,则返回 $-1$ 。数组可能包含重复元素。" +!!! question + + 给定一个长度为 $n$ 的有序数组 `nums` 。请查找并返回元素 `target` 在该数组中首次出现的索引。若数组中不包含该元素,则返回 $-1$ 。数组可能包含重复元素。 实际上,我们可以仅通过二分查找解决以上问题。方法的整体框架不变,先计算中点索引 `m` ,再判断 `target` 和 `nums[m]` 大小关系: diff --git a/docs/chapter_searching/replace_linear_by_hashing.md b/docs/chapter_searching/replace_linear_by_hashing.md index 12631147..9121935f 100755 --- a/docs/chapter_searching/replace_linear_by_hashing.md +++ b/docs/chapter_searching/replace_linear_by_hashing.md @@ -2,9 +2,9 @@ 在算法题中,**我们常通过将线性查找替换为哈希查找来降低算法的时间复杂度**。我们借助一个算法题来加深理解。 -!!! question "两数之和" +!!! question - 给定一个整数数组 `nums` 和一个整数目标值 `target` ,请在数组中搜索“和”为目标值 `target` 的两个整数,并返回他们在数组中的索引。注意,数组中同一个元素在答案里不能重复出现。返回任意一个解即可。 + 给定一个整数数组 `nums` 和一个目标元素 `target` ,请在数组中搜索“和”为 `target` 的两个元素,并返回它们的数组索引。返回任意一个解即可。 ## 线性查找:以时间换空间