diff --git a/docs-en/chapter_array_and_linkedlist/list.md b/docs-en/chapter_array_and_linkedlist/list.md index c576eeb2d..e562b009a 100755 --- a/docs-en/chapter_array_and_linkedlist/list.md +++ b/docs-en/chapter_array_and_linkedlist/list.md @@ -4,14 +4,14 @@ comments: true # 4.3   List -A "list" is an abstract data structure concept, representing an ordered collection of elements. It supports operations like element access, modification, addition, deletion, and traversal, without requiring users to consider capacity limitations. Lists can be implemented based on linked lists or arrays. +A "list" is an abstract data structure concept that represents an ordered collection of elements, supporting operations such as element access, modification, addition, deletion, and traversal, without requiring users to consider capacity limitations. Lists can be implemented based on linked lists or arrays. -- A linked list naturally functions as a list, supporting operations for adding, deleting, searching, and modifying elements, and can dynamically adjust its size. -- Arrays also support these operations, but due to their fixed length, they can be considered as a list with a length limit. +- A linked list inherently serves as a list, supporting operations for adding, deleting, searching, and modifying elements, with the flexibility to dynamically adjust its size. +- Arrays also support these operations, but due to their immutable length, they can be considered as a list with a length limit. -When using arrays to implement lists, **the fixed length property reduces the practicality of the list**. This is because we often cannot determine in advance how much data needs to be stored, making it difficult to choose an appropriate list length. If the length is too small, it may not meet the requirements; if too large, it may waste memory space. +When implementing lists using arrays, **the immutability of length reduces the practicality of the list**. This is because predicting the amount of data to be stored in advance is often challenging, making it difficult to choose an appropriate list length. If the length is too small, it may not meet the requirements; if too large, it may waste memory space. -To solve this problem, we can use a "dynamic array" to implement lists. It inherits the advantages of arrays and can dynamically expand during program execution. +To solve this problem, we can implement lists using a "dynamic array." It inherits the advantages of arrays and can dynamically expand during program execution. In fact, **many programming languages' standard libraries implement lists using dynamic arrays**, such as Python's `list`, Java's `ArrayList`, C++'s `vector`, and C#'s `List`. In the following discussion, we will consider "list" and "dynamic array" as synonymous concepts. @@ -19,7 +19,7 @@ In fact, **many programming languages' standard libraries implement lists using ### 1.   Initializing a List -We typically use two methods of initialization: "without initial values" and "with initial values". +We typically use two initialization methods: "without initial values" and "with initial values". === "Python" @@ -141,7 +141,7 @@ We typically use two methods of initialization: "without initial values" and "wi ### 2.   Accessing Elements -Lists are essentially arrays, so accessing and updating elements can be done in $O(1)$ time, which is very efficient. +Lists are essentially arrays, thus they can access and update elements in $O(1)$ time, which is very efficient. === "Python" @@ -258,9 +258,9 @@ Lists are essentially arrays, so accessing and updating elements can be done in nums.items[1] = 0; // Update the element at index 1 to 0 ``` -### 3.   Inserting and Deleting Elements +### 3.   Inserting and Removing Elements -Compared to arrays, lists can freely add and remove elements. Adding elements at the end of the list has a time complexity of $O(1)$, but the efficiency of inserting and deleting elements is still the same as in arrays, with a time complexity of $O(n)$. +Compared to arrays, lists offer more flexibility in adding and removing elements. While adding elements to the end of a list is an $O(1)$ operation, the efficiency of inserting and removing elements elsewhere in the list remains the same as in arrays, with a time complexity of $O(n)$. === "Python" @@ -488,9 +488,9 @@ Compared to arrays, lists can freely add and remove elements. Adding elements at _ = nums.orderedRemove(3); // Remove the element at index 3 ``` -### 4.   Traversing the List +### 4.   Iterating the List -Like arrays, lists can be traversed based on index, or by directly iterating over each element. +Similar to arrays, lists can be iterated either by using indices or by directly iterating through each element. === "Python" @@ -774,7 +774,7 @@ Given a new list `nums1`, we can append it to the end of the original list. ### 6.   Sorting the List -After sorting the list, we can use algorithms often tested in array-related algorithm problems, such as "binary search" and "two-pointer" algorithms. +Once the list is sorted, we can employ algorithms commonly used in array-related algorithm problems, such as "binary search" and "two-pointer" algorithms. === "Python" @@ -861,13 +861,13 @@ After sorting the list, we can use algorithms often tested in array-related algo ## 4.3.2   List Implementation -Many programming languages have built-in lists, such as Java, C++, Python, etc. Their implementations are quite complex, with very meticulous settings for parameters such as initial capacity and expansion multiplier. Interested readers can refer to the source code for learning. +Many programming languages come with built-in lists, including Java, C++, Python, etc. Their implementations tend to be intricate, featuring carefully considered settings for various parameters, like initial capacity and expansion factors. Readers who are curious can delve into the source code for further learning. -To deepen the understanding of how lists work, let's try implementing a simple version of a list, focusing on three key designs. +To enhance our understanding of how lists work, we will attempt to implement a simplified version of a list, focusing on three crucial design aspects: - **Initial Capacity**: Choose a reasonable initial capacity for the array. In this example, we choose 10 as the initial capacity. - **Size Recording**: Declare a variable `size` to record the current number of elements in the list, updating in real-time with element insertion and deletion. With this variable, we can locate the end of the list and determine whether expansion is needed. -- **Expansion Mechanism**: If the list's capacity is full when inserting an element, expansion is necessary. First, create a larger array based on the expansion multiplier, then move all elements of the current array to the new array. In this example, we define that each time the array will expand to twice its previous size. +- **Expansion Mechanism**: If the list reaches full capacity upon an element insertion, an expansion process is required. This involves creating a larger array based on the expansion factor, and then transferring all elements from the current array to the new one. In this example, we stipulate that the array size should double with each expansion. === "Python" diff --git a/docs-en/chapter_stack_and_queue/deque.md b/docs-en/chapter_stack_and_queue/deque.md index 094ff065e..5b08cbff7 100644 --- a/docs-en/chapter_stack_and_queue/deque.md +++ b/docs-en/chapter_stack_and_queue/deque.md @@ -577,8 +577,8 @@ The implementation code is as follows: if (fNext != nullptr) { fNext->prev = nullptr; front->next = nullptr; - delete front; } + delete front; front = fNext; // 更新头节点 // 队尾出队操作 } else { @@ -588,8 +588,8 @@ The implementation code is as follows: if (rPrev != nullptr) { rPrev->next = nullptr; rear->prev = nullptr; - delete rear; } + delete rear; rear = rPrev; // 更新尾节点 } queSize--; // 更新队列长度 diff --git a/docs-en/index.md b/docs-en/index.md index 7a5324b49..7389e475b 100644 --- a/docs-en/index.md +++ b/docs-en/index.md @@ -108,7 +108,7 @@ hide:
-

"Knowledge increases by sharing."

+

"Learning by teaching."

--- diff --git a/docs/chapter_introduction/index.md b/docs/chapter_introduction/index.md index 166543d0b..1aa715584 100644 --- a/docs/chapter_introduction/index.md +++ b/docs/chapter_introduction/index.md @@ -17,6 +17,14 @@ icon: material/calculator-variant-outline 她邀请你共舞,请紧跟她的步伐,踏入充满逻辑与美感的算法世界。 +计算机的出现给世界带来了巨大变革,它凭借高速的计算能力和出色的可编程性,成为了执行算法与处理数据的理想媒介。无论是电子游戏的逼真画面、自动驾驶的智能决策,还是 AlphaGo 的精彩棋局、ChatGPT 的自然交互,这些应用都是算法在计算机上的精妙演绎。 + +事实上,在计算机问世之前,算法和数据结构就已经存在于世界的各个角落。早期的算法相对简单,例如古代的计数方法和工具制作步骤等。随着文明的进步,算法逐渐变得更加精细和复杂。从巧夺天工的匠人技艺、到解放生产力的工业产品、再到宇宙运行的科学规律,几乎每一件平凡或令人惊叹的事物背后,都隐藏着精妙的算法思想。 + +同样,数据结构无处不在:大到社会网络,小到地铁线路,许多系统都可以建模为“图”;大到一个国家,小到一个家庭,社会的主要组织形式呈现出“树”的特征;冬天的衣服就像“栈”,最先穿上的最后才能脱下;羽毛球筒则如同“队列”,一端放入、另一端取出;字典就像一个“哈希表”,能够快速查找目标词条。 + +那么,什么是算法,它在我们日常生活中扮演着怎样的角色?接下来,我们将就这些问题展开探讨。 + ## 本章内容 - [1.1   算法无处不在](https://www.hello-algo.com/chapter_introduction/algorithms_are_everywhere/) diff --git a/docs/chapter_preface/index.md b/docs/chapter_preface/index.md index 92b7a55fa..a02336e49 100644 --- a/docs/chapter_preface/index.md +++ b/docs/chapter_preface/index.md @@ -17,6 +17,14 @@ icon: material/book-open-outline 愿这本书在你的脑海中轻轻响起,留下独特而深刻的旋律。 +两年前,我在力扣上分享了“剑指 Offer”系列题解,受到了许多读者的鼓励和支持。在与读者交流期间,我最常被问的一个问题是“如何入门算法”。逐渐地,我对这个问题产生了浓厚的兴趣。 + +两眼一抹黑地刷题似乎是最受欢迎的方法,简单、直接且有效。然而刷题就如同玩“扫雷”游戏,自学能力强的人能够顺利将地雷逐个排掉,而基础不足的人很可能被得的满头是包,并在挫折中步步退缩。通读教材也是一种常见做法,但对于面向求职的人来说,毕业论文、投递简历、准备笔试和面试已经消耗了大部分精力,啃厚重的书往往变成了一项艰巨的挑战。 + +如果你也面临类似的困扰,那么很幸运这本书“找”到了你。本书是我对这个问题给出的答案,即使不是最优解,也至少是一次积极的尝试。本书虽然不足以让你直接拿到 Offer,但会引导你探索数据结构与算法的“知识地图”,带你了解不同“地雷”的形状、大小和分布位置,让你掌握各种“排雷方法”。有了这些本领,相信你可以更加自如地刷题和阅读文献,逐步构建起完整的知识体系。 + +我深深赞同费曼教授所言:“Knowledge isn’t free. You have to pay attention.”从这个意义上看,这本书并非完全“免费”。为了不辜负你为本书所付出的宝贵“注意力”,我会竭尽所能,投入最大的“注意力”来完成本书的创作。 + ## 本章内容 - [0.1   关于本书](https://www.hello-algo.com/chapter_preface/about_the_book/) diff --git a/docs/chapter_sorting/insertion_sort.md b/docs/chapter_sorting/insertion_sort.md index bd24e05ec..a2f0216de 100755 --- a/docs/chapter_sorting/insertion_sort.md +++ b/docs/chapter_sorting/insertion_sort.md @@ -265,7 +265,7 @@ comments: true 插入排序的时间复杂度为 $O(n^2)$ ,而我们即将学习的快速排序的时间复杂度为 $O(n \log n)$ 。尽管插入排序的时间复杂度更高,**但在数据量较小的情况下,插入排序通常更快**。 -这个结论与线性查找和二分查找的适用情况的结论类似。快速排序这类 $O(n \log n)$ 的算法属于基于分治策略的排序算法,往往包含更多单元计算操作。而在数据量较小时,$n^2$ 和 $n \log n$ 的数值比较接近,复杂度不占主导地位;每轮中的单元操作数量起到决定性作用。 +这个结论与线性查找和二分查找的适用情况的结论类似。快速排序这类 $O(n \log n)$ 的算法属于基于分治策略的排序算法,往往包含更多单元计算操作。而在数据量较小时,$n^2$ 和 $n \log n$ 的数值比较接近,复杂度不占主导地位,每轮中的单元操作数量起到决定性作用。 实际上,许多编程语言(例如 Java)的内置排序函数采用了插入排序,大致思路为:对于长数组,采用基于分治策略的排序算法,例如快速排序;对于短数组,直接使用插入排序。 diff --git a/docs/chapter_stack_and_queue/deque.md b/docs/chapter_stack_and_queue/deque.md index 4c70d1d4a..8309eb919 100644 --- a/docs/chapter_stack_and_queue/deque.md +++ b/docs/chapter_stack_and_queue/deque.md @@ -577,8 +577,8 @@ comments: true if (fNext != nullptr) { fNext->prev = nullptr; front->next = nullptr; - delete front; } + delete front; front = fNext; // 更新头节点 // 队尾出队操作 } else { @@ -588,8 +588,8 @@ comments: true if (rPrev != nullptr) { rPrev->next = nullptr; rear->prev = nullptr; - delete rear; } + delete rear; rear = rPrev; // 更新尾节点 } queSize--; // 更新队列长度 diff --git a/docs/index.md b/docs/index.md index 03ce90f02..73e2818e3 100644 --- a/docs/index.md +++ b/docs/index.md @@ -250,7 +250,7 @@ hide:

互助学习

欢迎讨论与提问,读者间携手共进

-

"Knowledge increases by sharing."
“知识在分享中得以增长”

+

"Learning by teaching."
“教学相长”