From ca7b5c0ac2ae085913412ab367e2320d6f1f27f4 Mon Sep 17 00:00:00 2001 From: krahets Date: Sat, 2 Sep 2023 23:53:33 +0800 Subject: [PATCH] build --- chapter_backtracking/subset_sum_problem.md | 6 +-- .../time_complexity.md | 8 +-- .../binary_search_recur.md | 27 +++++++++- .../build_binary_tree_problem.md | 25 +++++++++- chapter_divide_and_conquer/hanota_problem.md | 49 ++++++++++++++----- .../dp_solution_pipeline.md | 2 +- chapter_graph/graph_operations.md | 22 ++++----- chapter_hashing/hash_algorithm.md | 6 +-- chapter_hashing/hash_collision.md | 2 +- chapter_sorting/bubble_sort.md | 16 +++--- chapter_sorting/bucket_sort.md | 2 +- chapter_sorting/selection_sort.md | 2 +- 12 files changed, 117 insertions(+), 50 deletions(-) diff --git a/chapter_backtracking/subset_sum_problem.md b/chapter_backtracking/subset_sum_problem.md index cf46eca90..42fba6d8f 100644 --- a/chapter_backtracking/subset_sum_problem.md +++ b/chapter_backtracking/subset_sum_problem.md @@ -1239,10 +1239,10 @@ comments: true /* 求解子集和 II */ vector *subsetSumII(vector *nums, int target) { - vector *state = newVector(); // 状态(子集) + vector *state = newVector(); // 状态(子集) qsort(nums->data, nums->size, sizeof(int *), comp); // 对 nums 进行排序 - int start = 0; // 子集和 - vector *res = newVector(); // 结果列表(子集列表) + int start = 0; // 子集和 + vector *res = newVector(); // 结果列表(子集列表) backtrack(state, target, nums, start, res); return res; } diff --git a/chapter_computational_complexity/time_complexity.md b/chapter_computational_complexity/time_complexity.md index 242a8a4d3..4345aaf18 100755 --- a/chapter_computational_complexity/time_complexity.md +++ b/chapter_computational_complexity/time_complexity.md @@ -1607,7 +1607,7 @@ $$ int count = 0; // 计数器 // 外循环:未排序区间为 [0, i] for (int i = nums.length - 1; i > 0; i--) { - // 内循环:将未排序区间 [0, i] 中的最大元素交换至该区间的最右端 + // 内循环:将未排序区间 [0, i] 中的最大元素交换至该区间的最右端 for (int j = 0; j < i; j++) { if (nums[j] > nums[j + 1]) { // 交换 nums[j] 与 nums[j + 1] @@ -1630,7 +1630,7 @@ $$ int count = 0; // 计数器 // 外循环:未排序区间为 [0, i] for (int i = nums.size() - 1; i > 0; i--) { - // 内循环:将未排序区间 [0, i] 中的最大元素交换至该区间的最右端 + // 内循环:将未排序区间 [0, i] 中的最大元素交换至该区间的最右端 for (int j = 0; j < i; j++) { if (nums[j] > nums[j + 1]) { // 交换 nums[j] 与 nums[j + 1] @@ -1653,7 +1653,7 @@ $$ count = 0 # 计数器 # 外循环:未排序区间为 [0, i] for i in range(len(nums) - 1, 0, -1): - # 内循环:将未排序区间 [0, i] 中的最大元素交换至该区间的最右端 + # 内循环:将未排序区间 [0, i] 中的最大元素交换至该区间的最右端 for j in range(i): if nums[j] > nums[j + 1]: # 交换 nums[j] 与 nums[j + 1] @@ -1741,7 +1741,7 @@ $$ int count = 0; // 计数器 // 外循环:未排序区间为 [0, i] for (int i = n - 1; i > 0; i--) { - // 内循环:将未排序区间 [0, i] 中的最大元素交换至该区间的最右端 + // 内循环:将未排序区间 [0, i] 中的最大元素交换至该区间的最右端 for (int j = 0; j < i; j++) { if (nums[j] > nums[j + 1]) { // 交换 nums[j] 与 nums[j + 1] diff --git a/chapter_divide_and_conquer/binary_search_recur.md b/chapter_divide_and_conquer/binary_search_recur.md index 806e04b9f..1fe2eca57 100644 --- a/chapter_divide_and_conquer/binary_search_recur.md +++ b/chapter_divide_and_conquer/binary_search_recur.md @@ -273,9 +273,32 @@ status: new === "Swift" ```swift title="binary_search_recur.swift" - [class]{}-[func]{dfs} + /* 二分查找:问题 f(i, j) */ + func dfs(nums: [Int], target: Int, i: Int, j: Int) -> Int { + // 若区间为空,代表无目标元素,则返回 -1 + if i > j { + return -1 + } + // 计算中点索引 m + let m = (i + j) / 2 + if nums[m] < target { + // 递归子问题 f(m+1, j) + return dfs(nums: nums, target: target, i: m + 1, j: j) + } else if nums[m] > target { + // 递归子问题 f(i, m-1) + return dfs(nums: nums, target: target, i: i, j: m - 1) + } else { + // 找到目标元素,返回其索引 + return m + } + } - [class]{}-[func]{binarySearch} + /* 二分查找 */ + func binarySearch(nums: [Int], target: Int) -> Int { + let n = nums.count + // 求解问题 f(0, n-1) + return dfs(nums: nums, target: target, i: 0, j: n - 1) + } ``` === "Zig" diff --git a/chapter_divide_and_conquer/build_binary_tree_problem.md b/chapter_divide_and_conquer/build_binary_tree_problem.md index 595e1e434..be0f0599a 100644 --- a/chapter_divide_and_conquer/build_binary_tree_problem.md +++ b/chapter_divide_and_conquer/build_binary_tree_problem.md @@ -316,9 +316,30 @@ status: new === "Swift" ```swift title="build_tree.swift" - [class]{}-[func]{dfs} + /* 构建二叉树:分治 */ + func dfs(preorder: [Int], inorder: [Int], hmap: [Int: Int], i: Int, l: Int, r: Int) -> TreeNode? { + // 子树区间为空时终止 + if r - l < 0 { + return nil + } + // 初始化根节点 + let root = TreeNode(x: preorder[i]) + // 查询 m ,从而划分左右子树 + let m = hmap[preorder[i]]! + // 子问题:构建左子树 + root.left = dfs(preorder: preorder, inorder: inorder, hmap: hmap, i: i + 1, l: l, r: m - 1) + // 子问题:构建右子树 + root.right = dfs(preorder: preorder, inorder: inorder, hmap: hmap, i: i + 1 + m - l, l: m + 1, r: r) + // 返回根节点 + return root + } - [class]{}-[func]{buildTree} + /* 构建二叉树 */ + func buildTree(preorder: [Int], inorder: [Int]) -> TreeNode? { + // 初始化哈希表,存储 inorder 元素到索引的映射 + let hmap = inorder.enumerated().reduce(into: [:]) { $0[$1.element] = $1.offset } + return dfs(preorder: preorder, inorder: inorder, hmap: hmap, i: 0, l: 0, r: inorder.count - 1) + } ``` === "Zig" diff --git a/chapter_divide_and_conquer/hanota_problem.md b/chapter_divide_and_conquer/hanota_problem.md index 95d20da0f..5786841e8 100644 --- a/chapter_divide_and_conquer/hanota_problem.md +++ b/chapter_divide_and_conquer/hanota_problem.md @@ -159,7 +159,7 @@ status: new } /* 求解汉诺塔 */ - void hanota(vector &A, vector &B, vector &C) { + void solveHanota(vector &A, vector &B, vector &C) { int n = A.size(); // 将 A 顶部 n 个圆盘借助 B 移到 C dfs(n, A, B, C); @@ -189,7 +189,7 @@ status: new # 子问题 f(i-1) :将 buf 顶部 i-1 个圆盘借助 src 移到 tar dfs(i - 1, buf, src, tar) - def hanota(A: list[int], B: list[int], C: list[int]): + def solve_hanota(A: list[int], B: list[int], C: list[int]): """求解汉诺塔""" n = len(A) # 将 A 顶部 n 个圆盘借助 B 移到 C @@ -225,7 +225,7 @@ status: new } /* 求解汉诺塔 */ - func hanota(A, B, C *list.List) { + func solveHanota(A, B, C *list.List) { n := A.Len() // 将 A 顶部 n 个圆盘借助 B 移到 C dfsHanota(n, A, B, C) @@ -259,7 +259,7 @@ status: new } /* 求解汉诺塔 */ - function hanota(A, B, C) { + function solveHanota(A, B, C) { const n = A.length; // 将 A 顶部 n 个圆盘借助 B 移到 C dfs(n, A, B, C); @@ -293,7 +293,7 @@ status: new } /* 求解汉诺塔 */ - function hanota(A: number[], B: number[], C: number[]): void { + function solveHanota(A: number[], B: number[], C: number[]): void { const n = A.length; // 将 A 顶部 n 个圆盘借助 B 移到 C dfs(n, A, B, C); @@ -307,7 +307,7 @@ status: new [class]{}-[func]{dfs} - [class]{}-[func]{hanota} + [class]{}-[func]{solveHanota} ``` === "C#" @@ -348,11 +348,36 @@ status: new === "Swift" ```swift title="hanota.swift" - [class]{}-[func]{move} + /* 移动一个圆盘 */ + func move(src: inout [Int], tar: inout [Int]) { + // 从 src 顶部拿出一个圆盘 + let pan = src.popLast()! + // 将圆盘放入 tar 顶部 + tar.append(pan) + } - [class]{}-[func]{dfs} + /* 求解汉诺塔:问题 f(i) */ + func dfs(i: Int, src: inout [Int], buf: inout [Int], tar: inout [Int]) { + // 若 src 只剩下一个圆盘,则直接将其移到 tar + if i == 1 { + move(src: &src, tar: &tar) + return + } + // 子问题 f(i-1) :将 src 顶部 i-1 个圆盘借助 tar 移到 buf + dfs(i: i - 1, src: &src, buf: &tar, tar: &buf) + // 子问题 f(1) :将 src 剩余一个圆盘移到 tar + move(src: &src, tar: &tar) + // 子问题 f(i-1) :将 buf 顶部 i-1 个圆盘借助 src 移到 tar + dfs(i: i - 1, src: &buf, buf: &src, tar: &tar) + } - [class]{}-[func]{hanota} + /* 求解汉诺塔 */ + func solveHanota(A: inout [Int], B: inout [Int], C: inout [Int]) { + let n = A.count + // 列表尾部是柱子顶部 + // 将 src 顶部 n 个圆盘借助 B 移到 C + dfs(i: n, src: &A, buf: &B, tar: &C) + } ``` === "Zig" @@ -362,7 +387,7 @@ status: new [class]{}-[func]{dfs} - [class]{}-[func]{hanota} + [class]{}-[func]{solveHanota} ``` === "Dart" @@ -392,7 +417,7 @@ status: new } /* 求解汉诺塔 */ - void hanota(List A, List B, List C) { + void solveHanota(List A, List B, List C) { int n = A.length; // 将 A 顶部 n 个圆盘借助 B 移到 C dfs(n, A, B, C); @@ -426,7 +451,7 @@ status: new } /* 求解汉诺塔 */ - fn hanota(A: &mut Vec, B: &mut Vec, C: &mut Vec) { + fn solve_hanota(A: &mut Vec, B: &mut Vec, C: &mut Vec) { let n = A.len() as i32; // 将 A 顶部 n 个圆盘借助 B 移到 C dfs(n, A, B, C); diff --git a/chapter_dynamic_programming/dp_solution_pipeline.md b/chapter_dynamic_programming/dp_solution_pipeline.md index 79689b712..f23b45038 100644 --- a/chapter_dynamic_programming/dp_solution_pipeline.md +++ b/chapter_dynamic_programming/dp_solution_pipeline.md @@ -250,7 +250,7 @@ $$ /* 最小路径和:暴力搜索 */ int minPathSumDFS(int[][] grid, int i, int j) { // 若为左上角单元格,则终止搜索 - if (i == 0 && j == 0){ + if (i == 0 && j == 0) { return grid[0][0]; } // 若行列索引越界,则返回 +∞ 代价 diff --git a/chapter_graph/graph_operations.md b/chapter_graph/graph_operations.md index 3dc154225..efe0f47e6 100644 --- a/chapter_graph/graph_operations.md +++ b/chapter_graph/graph_operations.md @@ -618,8 +618,6 @@ comments: true // 如果实际使用不大于预设空间,则直接初始化新空间 if (t->size < t->capacity) { t->vertices[t->size] = val; // 初始化新顶点值 - - for (int i = 0; i < t->size; i++) { t->adjMat[i][t->size] = 0; // 邻接矩新列阵置0 } @@ -659,7 +657,7 @@ comments: true free(t->adjMat); // 扩容后,指向新地址 - t->adjMat = tempMat; // 指向新的邻接矩阵地址 + t->adjMat = tempMat; // 指向新的邻接矩阵地址 t->capacity = t->size * 2; t->size++; } @@ -682,7 +680,7 @@ comments: true for (int j = index; j < t->size - 1; j++) { t->adjMat[i][j] = t->adjMat[i][j + 1]; // 被删除列后的所有列前移 } - } else { + } else { memcpy(t->adjMat[i], t->adjMat[i + 1], sizeof(unsigned int) * t->size); // 被删除行的下方所有行上移 for (int j = index; j < t->size; j++) { t->adjMat[i][j] = t->adjMat[i][j + 1]; // 被删除列后的所有列前移 @@ -725,12 +723,12 @@ comments: true /* 构造函数 */ graphAdjMat *newGraphAjdMat(unsigned int numberVertices, int *vertices, unsigned int **adjMat) { // 申请内存 - graphAdjMat *newGraph = (graphAdjMat *)malloc(sizeof(graphAdjMat)); // 为图分配内存 - newGraph->vertices = (int *)malloc(sizeof(int) * numberVertices * 2); // 为顶点列表分配内存 - newGraph->adjMat = (unsigned int **)malloc(sizeof(unsigned int *) * numberVertices * 2); // 为邻接矩阵分配二维内存 + graphAdjMat *newGraph = (graphAdjMat *)malloc(sizeof(graphAdjMat)); // 为图分配内存 + newGraph->vertices = (int *)malloc(sizeof(int) * numberVertices * 2); // 为顶点列表分配内存 + newGraph->adjMat = (unsigned int **)malloc(sizeof(unsigned int *) * numberVertices * 2); // 为邻接矩阵分配二维内存 unsigned int *temp = (unsigned int *)malloc(sizeof(unsigned int) * numberVertices * 2 * numberVertices * 2); // 为邻接矩阵分配一维内存 - newGraph->size = numberVertices; // 初始化顶点数量 - newGraph->capacity = numberVertices * 2; // 初始化图容量 + newGraph->size = numberVertices; // 初始化顶点数量 + newGraph->capacity = numberVertices * 2; // 初始化图容量 // 配置二维数组 for (int i = 0; i < numberVertices * 2; i++) { @@ -1730,7 +1728,7 @@ comments: true Node *temp = vet->linked->head->next; while (temp != 0) { removeLink(temp->val->linked, vet); // 删除与该顶点有关的边 - temp = temp->next; + temp = temp->next; } // 将顶点前移 @@ -1741,7 +1739,7 @@ comments: true t->verticesList[t->size - 1] = 0; // 将被删除顶点的位置置 0 t->size--; - //释放被删除顶点的内存 + // 释放内存 freeVertex(vet); } @@ -1773,7 +1771,7 @@ comments: true newGraph->size = 0; // 初始化顶点数量 newGraph->capacity = verticesCapacity; // 初始化顶点容量 // 返回图指针 - return newGraph; + return newGraph; } ``` diff --git a/chapter_hashing/hash_algorithm.md b/chapter_hashing/hash_algorithm.md index 3275803b1..5aa9f5e82 100644 --- a/chapter_hashing/hash_algorithm.md +++ b/chapter_hashing/hash_algorithm.md @@ -123,7 +123,7 @@ index = hash(key) % capacity int hash = 0; const int MODULUS = 1000000007; for (unsigned char c : key) { - cout<<(int)c< 0; i--) { - // 内循环:将未排序区间 [0, i] 中的最大元素交换至该区间的最右端 + // 内循环:将未排序区间 [0, i] 中的最大元素交换至该区间的最右端 for (int j = 0; j < i; j++) { if (nums[j] > nums[j + 1]) { // 交换 nums[j] 与 nums[j + 1] @@ -71,7 +71,7 @@ comments: true void bubbleSort(vector &nums) { // 外循环:未排序区间为 [0, i] for (int i = nums.size() - 1; i > 0; i--) { - // 内循环:将未排序区间 [0, i] 中的最大元素交换至该区间的最右端 + // 内循环:将未排序区间 [0, i] 中的最大元素交换至该区间的最右端 for (int j = 0; j < i; j++) { if (nums[j] > nums[j + 1]) { // 交换 nums[j] 与 nums[j + 1] @@ -91,7 +91,7 @@ comments: true n = len(nums) # 外循环:未排序区间为 [0, i] for i in range(n - 1, 0, -1): - # 内循环:将未排序区间 [0, i] 中的最大元素交换至该区间的最右端 + # 内循环:将未排序区间 [0, i] 中的最大元素交换至该区间的最右端 for j in range(i): if nums[j] > nums[j + 1]: # 交换 nums[j] 与 nums[j + 1] @@ -163,7 +163,7 @@ comments: true void bubbleSort(int nums[], int size) { // 外循环:未排序区间为 [0, i] for (int i = 0; i < size - 1; i++) { - // 内循环:将未排序区间 [0, i] 中的最大元素交换至该区间的最右端 + // 内循环:将未排序区间 [0, i] 中的最大元素交换至该区间的最右端 for (int j = 0; j < size - 1 - i; j++) { if (nums[j] > nums[j + 1]) { int temp = nums[j]; @@ -291,7 +291,7 @@ comments: true // 外循环:未排序区间为 [0, i] for (int i = nums.length - 1; i > 0; i--) { boolean flag = false; // 初始化标志位 - // 内循环:将未排序区间 [0, i] 中的最大元素交换至该区间的最右端 + // 内循环:将未排序区间 [0, i] 中的最大元素交换至该区间的最右端 for (int j = 0; j < i; j++) { if (nums[j] > nums[j + 1]) { // 交换 nums[j] 与 nums[j + 1] @@ -315,7 +315,7 @@ comments: true // 外循环:未排序区间为 [0, i] for (int i = nums.size() - 1; i > 0; i--) { bool flag = false; // 初始化标志位 - // 内循环:将未排序区间 [0, i] 中的最大元素交换至该区间的最右端 + // 内循环:将未排序区间 [0, i] 中的最大元素交换至该区间的最右端 for (int j = 0; j < i; j++) { if (nums[j] > nums[j + 1]) { // 交换 nums[j] 与 nums[j + 1] @@ -339,7 +339,7 @@ comments: true # 外循环:未排序区间为 [0, i] for i in range(n - 1, 0, -1): flag = False # 初始化标志位 - # 内循环:将未排序区间 [0, i] 中的最大元素交换至该区间的最右端 + # 内循环:将未排序区间 [0, i] 中的最大元素交换至该区间的最右端 for j in range(i): if nums[j] > nums[j + 1]: # 交换 nums[j] 与 nums[j + 1] @@ -426,7 +426,7 @@ comments: true // 外循环:未排序区间为 [0, i] for (int i = 0; i < size - 1; i++) { bool flag = false; - // 内循环:将未排序区间 [0, i] 中的最大元素交换至该区间的最右端 + // 内循环:将未排序区间 [0, i] 中的最大元素交换至该区间的最右端 for (int j = 0; j < size - 1 - i; j++) { if (nums[j] > nums[j + 1]) { int temp = nums[j]; diff --git a/chapter_sorting/bucket_sort.md b/chapter_sorting/bucket_sort.md index 0b344d456..71bb4edac 100644 --- a/chapter_sorting/bucket_sort.md +++ b/chapter_sorting/bucket_sort.md @@ -275,7 +275,7 @@ comments: true // 1. 将数组元素分配到各个桶中 foreach (float num in nums) { // 输入数据范围 [0, 1),使用 num * k 映射到索引范围 [0, k-1] - int i = (int) (num * k); + int i = (int)(num * k); // 将 num 添加进桶 i buckets[i].Add(num); } diff --git a/chapter_sorting/selection_sort.md b/chapter_sorting/selection_sort.md index 95347994c..a9508774a 100644 --- a/chapter_sorting/selection_sort.md +++ b/chapter_sorting/selection_sort.md @@ -186,7 +186,7 @@ comments: true int k = i; for (int j = i + 1; j < n; j++) { if (nums[j] < nums[k]) - k = j; // 记录最小元素的索引 + k = j; // 记录最小元素的索引 } // 将该最小元素与未排序区间的首个元素交换 int temp = nums[i];