From 2e130d4bbcc9b672b6c5b4178756b97c52b02887 Mon Sep 17 00:00:00 2001 From: Yudong Jin Date: Mon, 11 Dec 2023 00:42:00 +0800 Subject: [PATCH] Several bug fixes (#984) * Fix quick_sort.md * Disable instant loading for mathjax rendering * Fix the summary.md of chapter_sorting * Two bug fixes --- docs/chapter_searching/binary_search.md | 2 +- docs/chapter_sorting/quick_sort.md | 2 +- docs/chapter_sorting/radix_sort.md | 2 +- docs/chapter_sorting/summary.md | 2 +- mkdocs.yml | 2 +- overrides/javascripts/mathjax.js | 1 + 6 files changed, 6 insertions(+), 5 deletions(-) diff --git a/docs/chapter_searching/binary_search.md b/docs/chapter_searching/binary_search.md index d6713ae90..becc4db79 100755 --- a/docs/chapter_searching/binary_search.md +++ b/docs/chapter_searching/binary_search.md @@ -55,7 +55,7 @@ ## 区间表示方法 -除了上述双闭区间外,常见的区间表示还有“左闭右开”区间,定义为 $[0, n)$ ,即左边界包含自身,右边界不包含自身。在该表示下,区间 $[i, j]$ 在 $i = j$ 时为空。 +除了上述双闭区间外,常见的区间表示还有“左闭右开”区间,定义为 $[0, n)$ ,即左边界包含自身,右边界不包含自身。在该表示下,区间 $[i, j)$ 在 $i = j$ 时为空。 我们可以基于该表示实现具有相同功能的二分查找算法: diff --git a/docs/chapter_sorting/quick_sort.md b/docs/chapter_sorting/quick_sort.md index cb964da6f..a32387bb1 100755 --- a/docs/chapter_sorting/quick_sort.md +++ b/docs/chapter_sorting/quick_sort.md @@ -91,7 +91,7 @@ ## 尾递归优化 -**在某些输入下,快速排序可能占用空间较多**。以完全倒序的输入数组为例,设递归中的子数组长度为 $m$ ,每轮哨兵划分操作都将产生长度为 $0$ 的左子数组和长度为 $m - 1$ 的右子数组,这意味着每一层递归调用减少的问题规模非常小(只减少一个元素),递归树的高度会达到 $n - 1$ ,此时需要占用 $O(n)$ 大小的栈帧空间。 +**在某些输入下,快速排序可能占用空间较多**。以完全有序的输入数组为例,设递归中的子数组长度为 $m$ ,每轮哨兵划分操作都将产生长度为 $0$ 的左子数组和长度为 $m - 1$ 的右子数组,这意味着每一层递归调用减少的问题规模非常小(只减少一个元素),递归树的高度会达到 $n - 1$ ,此时需要占用 $O(n)$ 大小的栈帧空间。 为了防止栈帧空间的累积,我们可以在每轮哨兵排序完成后,比较两个子数组的长度,**仅对较短的子数组进行递归**。由于较短子数组的长度不会超过 $n / 2$ ,因此这种方法能确保递归深度不超过 $\log n$ ,从而将最差空间复杂度优化至 $O(\log n)$ 。代码如下所示: diff --git a/docs/chapter_sorting/radix_sort.md b/docs/chapter_sorting/radix_sort.md index eb71fa42a..cfa630201 100644 --- a/docs/chapter_sorting/radix_sort.md +++ b/docs/chapter_sorting/radix_sort.md @@ -38,4 +38,4 @@ $$ - **时间复杂度 $O(nk)$**:设数据量为 $n$、数据为 $d$ 进制、最大位数为 $k$ ,则对某一位执行计数排序使用 $O(n + d)$ 时间,排序所有 $k$ 位使用 $O((n + d)k)$ 时间。通常情况下,$d$ 和 $k$ 都相对较小,时间复杂度趋向 $O(n)$ 。 - **空间复杂度 $O(n + d)$、非原地排序**:与计数排序相同,基数排序需要借助长度为 $n$ 和 $d$ 的数组 `res` 和 `counter` 。 -- **稳定排序**:与计数排序相同。 +- **稳定排序**:当计数排序稳定时,基数排序也稳定;当计数排序不稳定时,基数排序无法保证得到正确的排序结果。 diff --git a/docs/chapter_sorting/summary.md b/docs/chapter_sorting/summary.md index 6149a8b41..8a5bbd137 100644 --- a/docs/chapter_sorting/summary.md +++ b/docs/chapter_sorting/summary.md @@ -28,7 +28,7 @@ 不行,当我们以最左端元素为基准数时,必须先“从右往左查找”再“从左往右查找”。这个结论有些反直觉,我们来剖析一下原因。 - 哨兵划分 `partition()` 的最后一步是交换 `nums[left]` 和 `nums[i]` 。完成交换后,基准数左边的元素都 `<=` 基准数,**这就要求最后一步交换前 `nums[left] >= nums[i]` 必须成立**。假设我们先“从左往右查找”,那么如果找不到比基准数更小的元素,**则会在 `i == j` 时跳出循环,此时可能 `nums[j] == nums[i] > nums[left]`**。也就是说,此时最后一步交换操作会把一个比基准数更大的元素交换至数组最左端,导致哨兵划分失败。 + 哨兵划分 `partition()` 的最后一步是交换 `nums[left]` 和 `nums[i]` 。完成交换后,基准数左边的元素都 `<=` 基准数,**这就要求最后一步交换前 `nums[left] >= nums[i]` 必须成立**。假设我们先“从左往右查找”,那么如果找不到比基准数更大的元素,**则会在 `i == j` 时跳出循环,此时可能 `nums[j] == nums[i] > nums[left]`**。也就是说,此时最后一步交换操作会把一个比基准数更大的元素交换至数组最左端,导致哨兵划分失败。 举个例子,给定数组 `[0, 0, 0, 0, 1]` ,如果先“从左向右查找”,哨兵划分后数组为 `[1, 0, 0, 0, 0]` ,这个结果是不正确的。 diff --git a/mkdocs.yml b/mkdocs.yml index 7c8db159a..249d3208d 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -30,7 +30,7 @@ theme: # - header.autohide # - navigation.expand - navigation.indexes - - navigation.instant + # - navigation.instant # - navigation.prune # - navigation.sections # - navigation.tabs diff --git a/overrides/javascripts/mathjax.js b/overrides/javascripts/mathjax.js index 117b04607..0631320c7 100644 --- a/overrides/javascripts/mathjax.js +++ b/overrides/javascripts/mathjax.js @@ -8,6 +8,7 @@ window.MathJax = { options: { ignoreHtmlClass: ".*|", processHtmlClass: "arithmatex", + enableMenu: false, }, };