From 26a2e7f171116a136dcf6406d87fb63596d420ab Mon Sep 17 00:00:00 2001 From: krahets Date: Sun, 20 Aug 2023 14:52:42 +0800 Subject: [PATCH] deploy --- chapter_appendix/installation/index.html | 2 +- chapter_array_and_linkedlist/array/index.html | 4 +- .../linked_list/index.html | 2 +- chapter_array_and_linkedlist/list/index.html | 2 +- .../summary/index.html | 2 +- .../subset_sum_problem/index.html | 2 +- chapter_computational_complexity/index.html | 4 +- .../performance_evaluation/index.html | 20 +-- .../space_complexity/index.html | 38 ++-- .../summary/index.html | 30 ++-- .../time_complexity/index.html | 164 +++++++++--------- .../basic_data_types/index.html | 2 +- .../number_encoding/index.html | 2 +- .../binary_search_recur/index.html | 2 +- chapter_divide_and_conquer/summary/index.html | 2 +- .../dp_problem_features/index.html | 2 +- .../edit_distance_problem/index.html | 2 +- .../intro_to_dynamic_programming/index.html | 4 +- .../summary/index.html | 2 +- .../unbounded_knapsack_problem/index.html | 2 +- chapter_graph/graph_operations/index.html | 2 +- .../max_product_cutting_problem/index.html | 2 +- chapter_heap/build_heap/index.html | 2 +- chapter_heap/heap/index.html | 52 +++--- .../algorithms_are_everywhere/index.html | 18 +- chapter_introduction/summary/index.html | 8 +- chapter_introduction/what_is_dsa/index.html | 14 +- chapter_searching/binary_search/index.html | 4 +- .../binary_search_edge/index.html | 2 +- .../searching_algorithm_revisited/index.html | 4 +- chapter_searching/summary/index.html | 4 +- chapter_sorting/bubble_sort/index.html | 2 +- chapter_sorting/heap_sort/index.html | 22 +-- chapter_sorting/insertion_sort/index.html | 2 +- chapter_sorting/merge_sort/index.html | 2 +- chapter_sorting/selection_sort/index.html | 2 +- chapter_sorting/sorting_algorithm/index.html | 2 +- chapter_stack_and_queue/stack/index.html | 2 +- chapter_tree/avl_tree/index.html | 24 +-- chapter_tree/binary_search_tree/index.html | 2 +- search/search_index.json | 2 +- sitemap.xml.gz | Bin 967 -> 967 bytes 42 files changed, 234 insertions(+), 230 deletions(-) diff --git a/chapter_appendix/installation/index.html b/chapter_appendix/installation/index.html index 6a732e820..2c11db449 100644 --- a/chapter_appendix/installation/index.html +++ b/chapter_appendix/installation/index.html @@ -3533,7 +3533,7 @@

16.1.3   C/C++ 环境

    -
  1. Windows 系统需要安装 MinGW配置教程),MacOS 自带 Clang 无需安装。
  2. +
  3. Windows 系统需要安装 MinGW配置教程),MacOS 自带 Clang 无须安装。
  4. 在 VSCode 的插件市场中搜索 c++ ,安装 C/C++ Extension Pack 。
  5. (可选)打开 Settings 页面,搜索 Clang_format_fallback Style 代码格式化选项,设置为 { BasedOnStyle: Microsoft, BreakBeforeBraces: Attach }
diff --git a/chapter_array_and_linkedlist/array/index.html b/chapter_array_and_linkedlist/array/index.html index 60bb5cac1..a2cfc5fd6 100644 --- a/chapter_array_and_linkedlist/array/index.html +++ b/chapter_array_and_linkedlist/array/index.html @@ -3926,7 +3926,7 @@

4.   删除元素

同理,如果我们想要删除索引 \(i\) 处的元素,则需要把索引 \(i\) 之后的元素都向前移动一位。

-

请注意,删除元素完成后,原先末尾的元素变得“无意义”了,所以我们无需特意去修改它。

+

请注意,删除元素完成后,原先末尾的元素变得“无意义”了,所以我们无须特意去修改它。

数组删除元素

图:数组删除元素

@@ -4571,7 +4571,7 @@

4.1.2   数组优点与局限性

数组存储在连续的内存空间内,且元素类型相同。这包含丰富的先验信息,系统可以利用这些信息来优化操作和运行效率,包括:

diff --git a/chapter_array_and_linkedlist/linked_list/index.html b/chapter_array_and_linkedlist/linked_list/index.html index 01cdb2018..1d2c23cb9 100644 --- a/chapter_array_and_linkedlist/linked_list/index.html +++ b/chapter_array_and_linkedlist/linked_list/index.html @@ -3523,7 +3523,7 @@

4.2   链表

内存空间是所有程序的公共资源,在一个复杂的系统运行环境下,空闲的内存空间可能散落在内存各处。我们知道,存储数组的内存空间必须是连续的,而当数组非常大时,内存可能无法提供如此大的连续空间。此时链表的灵活性优势就体现出来了。

-

「链表 Linked List」是一种线性数据结构,其中的每个元素都是一个节点对象,各个节点通过“引用”相连接。引用记录了下一个节点的内存地址,我们可以通过它从当前节点访问到下一个节点。这意味着链表的各个节点可以被分散存储在内存各处,它们的内存地址是无需连续的。

+

「链表 Linked List」是一种线性数据结构,其中的每个元素都是一个节点对象,各个节点通过“引用”相连接。引用记录了下一个节点的内存地址,我们可以通过它从当前节点访问到下一个节点。这意味着链表的各个节点可以被分散存储在内存各处,它们的内存地址是无须连续的。

链表定义与存储方式

图:链表定义与存储方式

diff --git a/chapter_array_and_linkedlist/list/index.html b/chapter_array_and_linkedlist/list/index.html index 97bb2e7d6..8ccd3f6ba 100644 --- a/chapter_array_and_linkedlist/list/index.html +++ b/chapter_array_and_linkedlist/list/index.html @@ -3509,7 +3509,7 @@

4.3   列表

数组长度不可变导致实用性降低。在实际中,我们可能事先无法确定需要存储多少数据,这使数组长度的选择变得困难。若长度过小,需要在持续添加数据时频繁扩容数组;若长度过大,则会造成内存空间的浪费。

-

为解决此问题,出现了一种被称为「动态数组 Dynamic Array」的数据结构,即长度可变的数组,也常被称为「列表 List」。列表基于数组实现,继承了数组的优点,并且可以在程序运行过程中动态扩容。我们可以在列表中自由地添加元素,而无需担心超过容量限制。

+

为解决此问题,出现了一种被称为「动态数组 Dynamic Array」的数据结构,即长度可变的数组,也常被称为「列表 List」。列表基于数组实现,继承了数组的优点,并且可以在程序运行过程中动态扩容。我们可以在列表中自由地添加元素,而无须担心超过容量限制。

4.3.1   列表常用操作

1.   初始化列表

我们通常使用“无初始值”和“有初始值”这两种初始化方法。

diff --git a/chapter_array_and_linkedlist/summary/index.html b/chapter_array_and_linkedlist/summary/index.html index c9865fc73..b122adee7 100644 --- a/chapter_array_and_linkedlist/summary/index.html +++ b/chapter_array_and_linkedlist/summary/index.html @@ -3450,7 +3450,7 @@

在 Python 中初始化 n = [1, 2, 3] 后,这 3 个元素的地址是相连的,但是初始化 m = [2, 1, 3] 会发现它们每个元素的 id 并不是连续的,而是分别跟 n 中的相同。这些元素地址不连续,那么 m 还是数组吗?

假如把列表元素换成链表节点 n = [n1, n2, n3, n4, n5] ,通常情况下这五个节点对象也是被分散存储在内存各处的。然而,给定一个列表索引,我们仍然可以在 \(O(1)\) 时间内获取到节点内存地址,从而访问到对应的节点。这是因为数组中存储的是节点的引用,而非节点本身。

-

与许多语言不同的是,在 Python 中数字也被包装为对象,列表中存储的不是数字本身,而是对数字的引用。因此,我们会发现两个数组中的相同数字拥有同一个 id ,并且这些数字的内存地址是无需连续的。

+

与许多语言不同的是,在 Python 中数字也被包装为对象,列表中存储的不是数字本身,而是对数字的引用。因此,我们会发现两个数组中的相同数字拥有同一个 id ,并且这些数字的内存地址是无须连续的。

C++ STL 里面的 std::list 已经实现了双向链表,但好像一些算法的书上都不怎么直接用这个,是不是有什么局限性呢?

diff --git a/chapter_backtracking/subset_sum_problem/index.html b/chapter_backtracking/subset_sum_problem/index.html index 673dc45dd..4c8bca5dd 100644 --- a/chapter_backtracking/subset_sum_problem/index.html +++ b/chapter_backtracking/subset_sum_problem/index.html @@ -3518,7 +3518,7 @@

1.   参考全排列解法

类似于全排列问题,我们可以把子集的生成过程想象成一系列选择的结果,并在选择过程中实时更新“元素和”,当元素和等于 target 时,就将子集记录至结果列表。

-

而与全排列问题不同的是,本题集合中的元素可以被无限次选取,因此无需借助 selected 布尔列表来记录元素是否已被选择。我们可以对全排列代码进行小幅修改,初步得到解题代码。

+

而与全排列问题不同的是,本题集合中的元素可以被无限次选取,因此无须借助 selected 布尔列表来记录元素是否已被选择。我们可以对全排列代码进行小幅修改,初步得到解题代码。

diff --git a/chapter_computational_complexity/index.html b/chapter_computational_complexity/index.html index bf8f9ed5b..3052fcb6f 100644 --- a/chapter_computational_complexity/index.html +++ b/chapter_computational_complexity/index.html @@ -3356,8 +3356,8 @@

Abstract

-

复杂度犹如浩瀚的算法宇宙中的指南针。

-

它引导我们在时间与空间的维度上深入探索,寻找更优雅的解决方案。

+

复杂度犹如浩瀚的算法宇宙中的时空向导。

+

它带领我们在时间与空间这两个维度上深入探索,寻找更优雅的解决方案。

本章内容

    diff --git a/chapter_computational_complexity/performance_evaluation/index.html b/chapter_computational_complexity/performance_evaluation/index.html index 51d906d0f..a2ab18aaf 100644 --- a/chapter_computational_complexity/performance_evaluation/index.html +++ b/chapter_computational_complexity/performance_evaluation/index.html @@ -3426,12 +3426,12 @@

    2.1   算法效率评估

    -

    在算法设计中,我们先后追求以下两个层面的目标:

    +

    在算法设计中,我们先后追求以下两个层面的目标。

    1. 找到问题解法:算法需要在规定的输入范围内,可靠地求得问题的正确解。
    2. 寻求最优解法:同一个问题可能存在多种解法,我们希望找到尽可能高效的算法。
    -

    因此在能够解决问题的前提下,算法效率成为主要的评价维度,包括:

    +

    因此,在能够解决问题的前提下,算法效率已成为衡量算法优劣的主要评价指标,它包括以下两个维度。

    • 时间效率:算法运行速度的快慢。
    • 空间效率:算法占用内存空间的大小。
    • @@ -3440,22 +3440,22 @@

      效率评估方法主要分为两种:实际测试和理论估算。

      2.1.1   实际测试

      假设我们现在有算法 A 和算法 B ,它们都能解决同一问题,现在需要对比这两个算法的效率。最直接的方法是找一台计算机,运行这两个算法,并监控记录它们的运行时间和内存占用情况。这种评估方式能够反映真实情况,但也存在较大局限性。

      -

      难以排除测试环境的干扰因素。硬件配置会影响算法的性能表现。比如在某台计算机中,算法 A 的运行时间比算法 B 短;但在另一台配置不同的计算机中,我们可能得到相反的测试结果。这意味着我们需要在各种机器上进行测试,统计平均效率,而这是不现实的。

      -

      展开完整测试非常耗费资源。随着输入数据量的变化,算法会表现出不同的效率。例如,在输入数据量较小时,算法 A 的运行时间比算法 B 更少;而输入数据量较大时,测试结果可能恰恰相反。因此,为了得到有说服力的结论,我们需要测试各种规模的输入数据,而这样需要耗费大量的计算资源。

      +

      一方面,难以排除测试环境的干扰因素。硬件配置会影响算法的性能表现。比如在某台计算机中,算法 A 的运行时间比算法 B 短;但在另一台配置不同的计算机中,我们可能得到相反的测试结果。这意味着我们需要在各种机器上进行测试,统计平均效率,而这是不现实的。

      +

      另一方面,展开完整测试非常耗费资源。随着输入数据量的变化,算法会表现出不同的效率。例如,在输入数据量较小时,算法 A 的运行时间比算法 B 更少;而输入数据量较大时,测试结果可能恰恰相反。因此,为了得到有说服力的结论,我们需要测试各种规模的输入数据,而这样需要耗费大量的计算资源。

      2.1.2   理论估算

      -

      由于实际测试具有较大的局限性,我们可以考虑仅通过一些计算来评估算法的效率。这种估算方法被称为「渐近复杂度分析 Asymptotic Complexity Analysis」,简称为「复杂度分析」。

      -

      复杂度分析评估的是算法执行所需的时间和空间资源。它被表示为一个函数,描述了随着输入数据大小的增加,算法所需时间(空间)的增长趋势。这个定义有些拗口,我们可以将其分为三个重点来理解:

      +

      由于实际测试具有较大的局限性,我们可以考虑仅通过一些计算来评估算法的效率。这种估算方法被称为「渐近复杂度分析 asymptotic complexity analysis」,简称「复杂度分析」。

      +

      复杂度分析评估的是算法运行所需的时间和空间资源,它描述了随着输入数据大小的增加,算法所需时间(空间)的增长趋势。这个定义有些拗口,我们可以将其分为三个重点来理解。

        -
      1. “时间(空间)”分别对应「时间复杂度 Time Complexity」和「空间复杂度 Space Complexity」。
      2. +
      3. “时间和空间资源”分别对应「时间复杂度 time complexity」和「空间复杂度 space complexity」。
      4. “随着输入数据大小的增加”意味着复杂度反映了算法运行效率与输入数据体量之间的关系。
      5. “增长趋势”表示复杂度分析关注的是算法时间与空间的增长趋势,而非具体的运行时间或占用空间。

      复杂度分析克服了实际测试方法的弊端。首先,它独立于测试环境,分析结果适用于所有运行平台。其次,它可以体现不同数据量下的算法效率,尤其是在大数据量下的算法性能。

      -

      如果你对复杂度分析的概念仍感到困惑,无需担心,我们会在后续章节详细介绍。

      +

      如果你对复杂度分析的概念仍感到困惑,无须担心,我们会在后续章节中详细介绍。

      2.1.3   复杂度的重要性

      复杂度分析为我们提供了一把评估算法效率的“标尺”,帮助我们衡量了执行某个算法所需的时间和空间资源,并使我们能够对比不同算法之间的效率。

      -

      复杂度是个数学概念,对于初学者可能比较抽象,学习难度相对较高。从这个角度看,复杂度分析可能不太适合作为第一章的内容。

      -

      然而,当我们讨论某个数据结构或算法的特点时,难以避免要分析其运行速度和空间使用情况。因此,在深入学习数据结构与算法之前,建议你先对复杂度建立初步的了解,能够完成简单算法的复杂度分析

      +

      复杂度是个数学概念,对于初学者可能比较抽象,学习难度相对较高。从这个角度看,复杂度分析可能不太适合作为第 1 章的内容。

      +

      然而,当我们讨论某个数据结构或算法的特点时,难以避免要分析其运行速度和空间使用情况。因此,在深入学习数据结构与算法之前,建议你先对复杂度建立初步的了解,以便能够完成简单算法的复杂度分析

      diff --git a/chapter_computational_complexity/space_complexity/index.html b/chapter_computational_complexity/space_complexity/index.html index 9777d0467..3034dd01c 100644 --- a/chapter_computational_complexity/space_complexity/index.html +++ b/chapter_computational_complexity/space_complexity/index.html @@ -3522,22 +3522,22 @@

      2.3   空间复杂度

      -

      「空间复杂度 Space Complexity」用于衡量算法占用内存空间随着数据量变大时的增长趋势。这个概念与时间复杂度非常类似,只需将“运行时间”替换为“占用内存空间”。

      +

      「空间复杂度 space complexity」用于衡量算法占用内存空间随着数据量变大时的增长趋势。这个概念与时间复杂度非常类似,只需将“运行时间”替换为“占用内存空间”。

      2.3.1   算法相关空间

      -

      算法运行过程中使用的内存空间主要包括以下几种:

      +

      算法在运行过程中使用的内存空间主要包括以下几种。

      • 输入空间:用于存储算法的输入数据。
      • -
      • 暂存空间:用于存储算法运行过程中的变量、对象、函数上下文等数据。
      • +
      • 暂存空间:用于存储算法在运行过程中的变量、对象、函数上下文等数据。
      • 输出空间:用于存储算法的输出数据。

      一般情况下,空间复杂度的统计范围是“暂存空间”加上“输出空间”。

      -

      暂存空间可以进一步划分为三个部分:

      +

      暂存空间可以进一步划分为三个部分。

      • 暂存数据:用于保存算法运行过程中的各种常量、变量、对象等。
      • 栈帧空间:用于保存调用函数的上下文数据。系统在每次调用函数时都会在栈顶部创建一个栈帧,函数返回后,栈帧空间会被释放。
      • 指令空间:用于保存编译后的程序指令,在实际统计中通常忽略不计。
      -

      因此在分析一段程序的空间复杂度时,我们通常统计暂存数据、输出数据、栈帧空间三部分

      +

      在分析一段程序的空间复杂度时,我们通常统计暂存数据、栈帧空间和输出数据三部分

      算法使用的相关空间

      图:算法使用的相关空间

      @@ -3786,7 +3786,7 @@

2.3.2   推算方法

-

空间复杂度的推算方法与时间复杂度大致相同,只需将统计对象从“计算操作数量”转为“使用空间大小”。

+

空间复杂度的推算方法与时间复杂度大致相同,只需将统计对象从“操作数量”转为“使用空间大小”。

而与时间复杂度不同的是,我们通常只关注「最差空间复杂度」。这是因为内存空间是一项硬性要求,我们必须确保在所有输入数据下都有足够的内存空间预留。

观察以下代码,最差空间复杂度中的“最差”有两层含义。

    @@ -3902,7 +3902,7 @@
-

在递归函数中,需要注意统计栈帧空间。例如以下代码:

+

在递归函数中,需要注意统计栈帧空间。例如在以下代码中: