Squash the language code blocks and fix list.md (#865)

This commit is contained in:
Yudong Jin 2023-10-16 12:06:00 -05:00 committed by GitHub
parent 346c8451de
commit faa44fecd2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
52 changed files with 409 additions and 10482 deletions

View file

@ -123,76 +123,8 @@
在数组中访问元素是非常高效的,我们可以在 $O(1)$ 时间内随机访问数组中的任意一个元素。
=== "Python"
```python title="array.py"
[class]{}-[func]{random_access}
```
=== "C++"
```cpp title="array.cpp"
[class]{}-[func]{randomAccess}
```
=== "Java"
```java title="array.java"
[class]{array}-[func]{randomAccess}
```
=== "C#"
```csharp title="array.cs"
[class]{array}-[func]{RandomAccess}
```
=== "Go"
```go title="array.go"
[class]{}-[func]{randomAccess}
```
=== "Swift"
```swift title="array.swift"
[class]{}-[func]{randomAccess}
```
=== "JS"
```javascript title="array.js"
[class]{}-[func]{randomAccess}
```
=== "TS"
```typescript title="array.ts"
[class]{}-[func]{randomAccess}
```
=== "Dart"
```dart title="array.dart"
[class]{}-[func]{randomAccess}
```
=== "Rust"
```rust title="array.rs"
[class]{}-[func]{random_access}
```
=== "C"
```c title="array.c"
[class]{}-[func]{randomAccess}
```
=== "Zig"
```zig title="array.zig"
[class]{}-[func]{randomAccess}
```src
[file]{array}-[class]{}-[func]{random_access}
```
### 插入元素
@ -203,76 +135,8 @@
值得注意的是,由于数组的长度是固定的,因此插入一个元素必定会导致数组尾部元素的“丢失”。我们将这个问题的解决方案留在列表章节中讨论。
=== "Python"
```python title="array.py"
[class]{}-[func]{insert}
```
=== "C++"
```cpp title="array.cpp"
[class]{}-[func]{insert}
```
=== "Java"
```java title="array.java"
[class]{array}-[func]{insert}
```
=== "C#"
```csharp title="array.cs"
[class]{array}-[func]{Insert}
```
=== "Go"
```go title="array.go"
[class]{}-[func]{insert}
```
=== "Swift"
```swift title="array.swift"
[class]{}-[func]{insert}
```
=== "JS"
```javascript title="array.js"
[class]{}-[func]{insert}
```
=== "TS"
```typescript title="array.ts"
[class]{}-[func]{insert}
```
=== "Dart"
```dart title="array.dart"
[class]{}-[func]{insert}
```
=== "Rust"
```rust title="array.rs"
[class]{}-[func]{insert}
```
=== "C"
```c title="array.c"
[class]{}-[func]{insert}
```
=== "Zig"
```zig title="array.zig"
[class]{}-[func]{insert}
```src
[file]{array}-[class]{}-[func]{insert}
```
### 删除元素
@ -283,76 +147,8 @@
请注意,删除元素完成后,原先末尾的元素变得“无意义”了,所以我们无须特意去修改它。
=== "Python"
```python title="array.py"
[class]{}-[func]{remove}
```
=== "C++"
```cpp title="array.cpp"
[class]{}-[func]{remove}
```
=== "Java"
```java title="array.java"
[class]{array}-[func]{remove}
```
=== "C#"
```csharp title="array.cs"
[class]{array}-[func]{Remove}
```
=== "Go"
```go title="array.go"
[class]{}-[func]{remove}
```
=== "Swift"
```swift title="array.swift"
[class]{}-[func]{remove}
```
=== "JS"
```javascript title="array.js"
[class]{}-[func]{remove}
```
=== "TS"
```typescript title="array.ts"
[class]{}-[func]{remove}
```
=== "Dart"
```dart title="array.dart"
[class]{}-[func]{remove}
```
=== "Rust"
```rust title="array.rs"
[class]{}-[func]{remove}
```
=== "C"
```c title="array.c"
[class]{}-[func]{removeItem}
```
=== "Zig"
```zig title="array.zig"
[class]{}-[func]{remove}
```src
[file]{array}-[class]{}-[func]{remove}
```
总的来看,数组的插入与删除操作有以下缺点。
@ -365,76 +161,8 @@
在大多数编程语言中,我们既可以通过索引遍历数组,也可以直接遍历获取数组中的每个元素。
=== "Python"
```python title="array.py"
[class]{}-[func]{traverse}
```
=== "C++"
```cpp title="array.cpp"
[class]{}-[func]{traverse}
```
=== "Java"
```java title="array.java"
[class]{array}-[func]{traverse}
```
=== "C#"
```csharp title="array.cs"
[class]{array}-[func]{Traverse}
```
=== "Go"
```go title="array.go"
[class]{}-[func]{traverse}
```
=== "Swift"
```swift title="array.swift"
[class]{}-[func]{traverse}
```
=== "JS"
```javascript title="array.js"
[class]{}-[func]{traverse}
```
=== "TS"
```typescript title="array.ts"
[class]{}-[func]{traverse}
```
=== "Dart"
```dart title="array.dart"
[class]{}-[func]{traverse}
```
=== "Rust"
```rust title="array.rs"
[class]{}-[func]{traverse}
```
=== "C"
```c title="array.c"
[class]{}-[func]{traverse}
```
=== "Zig"
```zig title="array.zig"
[class]{}-[func]{traverse}
```src
[file]{array}-[class]{}-[func]{traverse}
```
### 查找元素
@ -443,76 +171,8 @@
因为数组是线性数据结构,所以上述查找操作被称为“线性查找”。
=== "Python"
```python title="array.py"
[class]{}-[func]{find}
```
=== "C++"
```cpp title="array.cpp"
[class]{}-[func]{find}
```
=== "Java"
```java title="array.java"
[class]{array}-[func]{find}
```
=== "C#"
```csharp title="array.cs"
[class]{array}-[func]{Find}
```
=== "Go"
```go title="array.go"
[class]{}-[func]{find}
```
=== "Swift"
```swift title="array.swift"
[class]{}-[func]{find}
```
=== "JS"
```javascript title="array.js"
[class]{}-[func]{find}
```
=== "TS"
```typescript title="array.ts"
[class]{}-[func]{find}
```
=== "Dart"
```dart title="array.dart"
[class]{}-[func]{find}
```
=== "Rust"
```rust title="array.rs"
[class]{}-[func]{find}
```
=== "C"
```c title="array.c"
[class]{}-[func]{find}
```
=== "Zig"
```zig title="array.zig"
[class]{}-[func]{find}
```src
[file]{array}-[class]{}-[func]{find}
```
### 扩容数组
@ -521,76 +181,8 @@
如果我们希望扩容数组,则需重新建立一个更大的数组,然后把原数组元素依次拷贝到新数组。这是一个 $O(n)$ 的操作,在数组很大的情况下是非常耗时的。
=== "Python"
```python title="array.py"
[class]{}-[func]{extend}
```
=== "C++"
```cpp title="array.cpp"
[class]{}-[func]{extend}
```
=== "Java"
```java title="array.java"
[class]{array}-[func]{extend}
```
=== "C#"
```csharp title="array.cs"
[class]{array}-[func]{Extend}
```
=== "Go"
```go title="array.go"
[class]{}-[func]{extend}
```
=== "Swift"
```swift title="array.swift"
[class]{}-[func]{extend}
```
=== "JS"
```javascript title="array.js"
[class]{}-[func]{extend}
```
=== "TS"
```typescript title="array.ts"
[class]{}-[func]{extend}
```
=== "Dart"
```dart title="array.dart"
[class]{}-[func]{extend}
```
=== "Rust"
```rust title="array.rs"
[class]{}-[func]{extend}
```
=== "C"
```c title="array.c"
[class]{}-[func]{extend}
```
=== "Zig"
```zig title="array.zig"
[class]{}-[func]{extend}
```src
[file]{array}-[class]{}-[func]{extend}
```
## 数组优点与局限性

View file

@ -405,76 +405,8 @@
![链表插入节点示例](linked_list.assets/linkedlist_insert_node.png)
=== "Python"
```python title="linked_list.py"
[class]{}-[func]{insert}
```
=== "C++"
```cpp title="linked_list.cpp"
[class]{}-[func]{insert}
```
=== "Java"
```java title="linked_list.java"
[class]{linked_list}-[func]{insert}
```
=== "C#"
```csharp title="linked_list.cs"
[class]{linked_list}-[func]{Insert}
```
=== "Go"
```go title="linked_list.go"
[class]{}-[func]{insertNode}
```
=== "Swift"
```swift title="linked_list.swift"
[class]{}-[func]{insert}
```
=== "JS"
```javascript title="linked_list.js"
[class]{}-[func]{insert}
```
=== "TS"
```typescript title="linked_list.ts"
[class]{}-[func]{insert}
```
=== "Dart"
```dart title="linked_list.dart"
[class]{}-[func]{insert}
```
=== "Rust"
```rust title="linked_list.rs"
[class]{}-[func]{insert}
```
=== "C"
```c title="linked_list.c"
[class]{}-[func]{insert}
```
=== "Zig"
```zig title="linked_list.zig"
[class]{}-[func]{insert}
```src
[file]{linked_list}-[class]{}-[func]{insert}
```
### 删除节点
@ -485,228 +417,24 @@
![链表删除节点](linked_list.assets/linkedlist_remove_node.png)
=== "Python"
```python title="linked_list.py"
[class]{}-[func]{remove}
```
=== "C++"
```cpp title="linked_list.cpp"
[class]{}-[func]{remove}
```
=== "Java"
```java title="linked_list.java"
[class]{linked_list}-[func]{remove}
```
=== "C#"
```csharp title="linked_list.cs"
[class]{linked_list}-[func]{Remove}
```
=== "Go"
```go title="linked_list.go"
[class]{}-[func]{removeItem}
```
=== "Swift"
```swift title="linked_list.swift"
[class]{}-[func]{remove}
```
=== "JS"
```javascript title="linked_list.js"
[class]{}-[func]{remove}
```
=== "TS"
```typescript title="linked_list.ts"
[class]{}-[func]{remove}
```
=== "Dart"
```dart title="linked_list.dart"
[class]{}-[func]{remove}
```
=== "Rust"
```rust title="linked_list.rs"
[class]{}-[func]{remove}
```
=== "C"
```c title="linked_list.c"
[class]{}-[func]{removeItem}
```
=== "Zig"
```zig title="linked_list.zig"
[class]{}-[func]{remove}
```src
[file]{linked_list}-[class]{}-[func]{remove}
```
### 访问节点
**在链表访问节点的效率较低**。如上节所述,我们可以在 $O(1)$ 时间下访问数组中的任意元素。链表则不然,程序需要从头节点出发,逐个向后遍历,直至找到目标节点。也就是说,访问链表的第 $i$ 个节点需要循环 $i - 1$ 轮,时间复杂度为 $O(n)$ 。
=== "Python"
```python title="linked_list.py"
[class]{}-[func]{access}
```
=== "C++"
```cpp title="linked_list.cpp"
[class]{}-[func]{access}
```
=== "Java"
```java title="linked_list.java"
[class]{linked_list}-[func]{access}
```
=== "C#"
```csharp title="linked_list.cs"
[class]{linked_list}-[func]{Access}
```
=== "Go"
```go title="linked_list.go"
[class]{}-[func]{access}
```
=== "Swift"
```swift title="linked_list.swift"
[class]{}-[func]{access}
```
=== "JS"
```javascript title="linked_list.js"
[class]{}-[func]{access}
```
=== "TS"
```typescript title="linked_list.ts"
[class]{}-[func]{access}
```
=== "Dart"
```dart title="linked_list.dart"
[class]{}-[func]{access}
```
=== "Rust"
```rust title="linked_list.rs"
[class]{}-[func]{access}
```
=== "C"
```c title="linked_list.c"
[class]{}-[func]{access}
```
=== "Zig"
```zig title="linked_list.zig"
[class]{}-[func]{access}
```src
[file]{linked_list}-[class]{}-[func]{access}
```
### 查找节点
遍历链表,查找链表内值为 `target` 的节点,输出节点在链表中的索引。此过程也属于线性查找。
=== "Python"
```python title="linked_list.py"
[class]{}-[func]{find}
```
=== "C++"
```cpp title="linked_list.cpp"
[class]{}-[func]{find}
```
=== "Java"
```java title="linked_list.java"
[class]{linked_list}-[func]{find}
```
=== "C#"
```csharp title="linked_list.cs"
[class]{linked_list}-[func]{Find}
```
=== "Go"
```go title="linked_list.go"
[class]{}-[func]{findNode}
```
=== "Swift"
```swift title="linked_list.swift"
[class]{}-[func]{find}
```
=== "JS"
```javascript title="linked_list.js"
[class]{}-[func]{find}
```
=== "TS"
```typescript title="linked_list.ts"
[class]{}-[func]{find}
```
=== "Dart"
```dart title="linked_list.dart"
[class]{}-[func]{find}
```
=== "Rust"
```rust title="linked_list.rs"
[class]{}-[func]{find}
```
=== "C"
```c title="linked_list.c"
[class]{}-[func]{find}
```
=== "Zig"
```zig title="linked_list.zig"
[class]{}-[func]{find}
```src
[file]{linked_list}-[class]{}-[func]{find}
```
## 数组 VS 链表

View file

@ -1,8 +1,15 @@
# 列表
**数组长度不可变导致实用性降低**。在实际中,我们可能事先无法确定需要存储多少数据,这使数组长度的选择变得困难。若长度过小,需要在持续添加数据时频繁扩容数组;若长度过大,则会造成内存空间的浪费
「列表 list」是一个抽象的数据结构概念它表示元素的有序集合支持元素访问、修改、添加、删除和遍历等操作无需使用者考虑容量限制的问题。列表可以基于链表或数组实现
为解决此问题,出现了一种被称为「动态数组 dynamic array」的数据结构即长度可变的数组也常被称为「列表 list」。列表基于数组实现继承了数组的优点并且可以在程序运行过程中动态扩容。我们可以在列表中自由地添加元素而无须担心超过容量限制。
- 链表天然可以被看作是一个列表,其支持元素增删查改操作,并且可以灵活动态扩容。
- 数组也支持元素增删查改,但由于其长度不可变,因此只能被看作是一个具有长度限制的列表。
当使用数组实现列表时,**长度不可变的性质会导致列表的实用性降低**。这是因为我们通常无法事先确定需要存储多少数据,从而难以选择合适的列表长度。若长度过小,则很可能无法满足使用需求;若长度过大,则会造成内存空间的浪费。
为解决此问题,我们可以使用「动态数组 dynamic array」来实现列表。它继承了数组的各项优点并且可以在程序运行过程中进行动态扩容。
实际上,**许多编程语言中的标准库提供的列表都是基于动态数组实现的**,例如 Python 中的 `list` 、Java 中的 `ArrayList` 、C++ 中的 `vector` 和 C# 中的 `List` 等。在接下来的讨论中,我们将把“列表”和“动态数组”视为等同的概念。
## 列表常用操作
@ -860,74 +867,6 @@
- **数量记录**:声明一个变量 `size` ,用于记录列表当前元素数量,并随着元素插入和删除实时更新。根据此变量,我们可以定位列表尾部,以及判断是否需要扩容。
- **扩容机制**:若插入元素时列表容量已满,则需要进行扩容。首先根据扩容倍数创建一个更大的数组,再将当前数组的所有元素依次移动至新数组。在本示例中,我们规定每次将数组扩容至之前的 2 倍。
=== "Python"
```python title="my_list.py"
[class]{MyList}-[func]{}
```
=== "C++"
```cpp title="my_list.cpp"
[class]{MyList}-[func]{}
```
=== "Java"
```java title="my_list.java"
[class]{MyList}-[func]{}
```
=== "C#"
```csharp title="my_list.cs"
[class]{MyList}-[func]{}
```
=== "Go"
```go title="my_list.go"
[class]{myList}-[func]{}
```
=== "Swift"
```swift title="my_list.swift"
[class]{MyList}-[func]{}
```
=== "JS"
```javascript title="my_list.js"
[class]{MyList}-[func]{}
```
=== "TS"
```typescript title="my_list.ts"
[class]{MyList}-[func]{}
```
=== "Dart"
```dart title="my_list.dart"
[class]{MyList}-[func]{}
```
=== "Rust"
```rust title="my_list.rs"
[class]{MyList}-[func]{}
```
=== "C"
```c title="my_list.c"
[class]{myList}-[func]{}
```
=== "Zig"
```zig title="my_list.zig"
[class]{MyList}-[func]{}
```src
[file]{my_list}-[class]{my_list}-[func]{}
```

View file

@ -10,76 +10,8 @@
对于此题,我们前序遍历这颗树,并判断当前节点的值是否为 $7$ ,若是则将该节点的值加入到结果列表 `res` 之中。相关过程实现如下图和以下代码所示。
=== "Python"
```python title="preorder_traversal_i_compact.py"
[class]{}-[func]{pre_order}
```
=== "C++"
```cpp title="preorder_traversal_i_compact.cpp"
[class]{}-[func]{preOrder}
```
=== "Java"
```java title="preorder_traversal_i_compact.java"
[class]{preorder_traversal_i_compact}-[func]{preOrder}
```
=== "C#"
```csharp title="preorder_traversal_i_compact.cs"
[class]{preorder_traversal_i_compact}-[func]{PreOrder}
```
=== "Go"
```go title="preorder_traversal_i_compact.go"
[class]{}-[func]{preOrderI}
```
=== "Swift"
```swift title="preorder_traversal_i_compact.swift"
[class]{}-[func]{preOrder}
```
=== "JS"
```javascript title="preorder_traversal_i_compact.js"
[class]{}-[func]{preOrder}
```
=== "TS"
```typescript title="preorder_traversal_i_compact.ts"
[class]{}-[func]{preOrder}
```
=== "Dart"
```dart title="preorder_traversal_i_compact.dart"
[class]{}-[func]{preOrder}
```
=== "Rust"
```rust title="preorder_traversal_i_compact.rs"
[class]{}-[func]{pre_order}
```
=== "C"
```c title="preorder_traversal_i_compact.c"
[class]{}-[func]{preOrder}
```
=== "Zig"
```zig title="preorder_traversal_i_compact.zig"
[class]{}-[func]{preOrder}
```src
[file]{preorder_traversal_i_compact}-[class]{}-[func]{pre_order}
```
![在前序遍历中搜索节点](backtracking_algorithm.assets/preorder_find_nodes.png)
@ -98,76 +30,8 @@
在例题一代码的基础上,我们需要借助一个列表 `path` 记录访问过的节点路径。当访问到值为 $7$ 的节点时,则复制 `path` 并添加进结果列表 `res` 。遍历完成后,`res` 中保存的就是所有的解。
=== "Python"
```python title="preorder_traversal_ii_compact.py"
[class]{}-[func]{pre_order}
```
=== "C++"
```cpp title="preorder_traversal_ii_compact.cpp"
[class]{}-[func]{preOrder}
```
=== "Java"
```java title="preorder_traversal_ii_compact.java"
[class]{preorder_traversal_ii_compact}-[func]{preOrder}
```
=== "C#"
```csharp title="preorder_traversal_ii_compact.cs"
[class]{preorder_traversal_ii_compact}-[func]{PreOrder}
```
=== "Go"
```go title="preorder_traversal_ii_compact.go"
[class]{}-[func]{preOrderII}
```
=== "Swift"
```swift title="preorder_traversal_ii_compact.swift"
[class]{}-[func]{preOrder}
```
=== "JS"
```javascript title="preorder_traversal_ii_compact.js"
[class]{}-[func]{preOrder}
```
=== "TS"
```typescript title="preorder_traversal_ii_compact.ts"
[class]{}-[func]{preOrder}
```
=== "Dart"
```dart title="preorder_traversal_ii_compact.dart"
[class]{}-[func]{preOrder}
```
=== "Rust"
```rust title="preorder_traversal_ii_compact.rs"
[class]{}-[func]{pre_order}
```
=== "C"
```c title="preorder_traversal_ii_compact.c"
[class]{}-[func]{preOrder}
```
=== "Zig"
```zig title="preorder_traversal_ii_compact.zig"
[class]{}-[func]{preOrder}
```src
[file]{preorder_traversal_ii_compact}-[class]{}-[func]{pre_order}
```
在每次“尝试”中,我们通过将当前节点添加进 `path` 来记录路径;而在“回退”前,我们需要将该节点从 `path` 中弹出,**以恢复本次尝试之前的状态**。
@ -217,76 +81,8 @@
为了满足以上约束条件,**我们需要添加剪枝操作**:在搜索过程中,若遇到值为 $3$ 的节点,则提前返回,停止继续搜索。
=== "Python"
```python title="preorder_traversal_iii_compact.py"
[class]{}-[func]{pre_order}
```
=== "C++"
```cpp title="preorder_traversal_iii_compact.cpp"
[class]{}-[func]{preOrder}
```
=== "Java"
```java title="preorder_traversal_iii_compact.java"
[class]{preorder_traversal_iii_compact}-[func]{preOrder}
```
=== "C#"
```csharp title="preorder_traversal_iii_compact.cs"
[class]{preorder_traversal_iii_compact}-[func]{PreOrder}
```
=== "Go"
```go title="preorder_traversal_iii_compact.go"
[class]{}-[func]{preOrderIII}
```
=== "Swift"
```swift title="preorder_traversal_iii_compact.swift"
[class]{}-[func]{preOrder}
```
=== "JS"
```javascript title="preorder_traversal_iii_compact.js"
[class]{}-[func]{preOrder}
```
=== "TS"
```typescript title="preorder_traversal_iii_compact.ts"
[class]{}-[func]{preOrder}
```
=== "Dart"
```dart title="preorder_traversal_iii_compact.dart"
[class]{}-[func]{preOrder}
```
=== "Rust"
```rust title="preorder_traversal_iii_compact.rs"
[class]{}-[func]{pre_order}
```
=== "C"
```c title="preorder_traversal_iii_compact.c"
[class]{}-[func]{preOrder}
```
=== "Zig"
```zig title="preorder_traversal_iii_compact.zig"
[class]{}-[func]{preOrder}
```src
[file]{preorder_traversal_iii_compact}-[class]{}-[func]{pre_order}
```
剪枝是一个非常形象的名词。如下图所示,在搜索过程中,**我们“剪掉”了不满足约束条件的搜索分支**,避免许多无意义的尝试,从而提高了搜索效率。
@ -589,196 +385,8 @@
接下来,我们基于框架代码来解决例题三。状态 `state` 为节点遍历路径,选择 `choices` 为当前节点的左子节点和右子节点,结果 `res` 是路径列表。
=== "Python"
```python title="preorder_traversal_iii_template.py"
[class]{}-[func]{is_solution}
[class]{}-[func]{record_solution}
[class]{}-[func]{is_valid}
[class]{}-[func]{make_choice}
[class]{}-[func]{undo_choice}
[class]{}-[func]{backtrack}
```
=== "C++"
```cpp title="preorder_traversal_iii_template.cpp"
[class]{}-[func]{isSolution}
[class]{}-[func]{recordSolution}
[class]{}-[func]{isValid}
[class]{}-[func]{makeChoice}
[class]{}-[func]{undoChoice}
[class]{}-[func]{backtrack}
```
=== "Java"
```java title="preorder_traversal_iii_template.java"
[class]{preorder_traversal_iii_template}-[func]{isSolution}
[class]{preorder_traversal_iii_template}-[func]{recordSolution}
[class]{preorder_traversal_iii_template}-[func]{isValid}
[class]{preorder_traversal_iii_template}-[func]{makeChoice}
[class]{preorder_traversal_iii_template}-[func]{undoChoice}
[class]{preorder_traversal_iii_template}-[func]{backtrack}
```
=== "C#"
```csharp title="preorder_traversal_iii_template.cs"
[class]{preorder_traversal_iii_template}-[func]{IsSolution}
[class]{preorder_traversal_iii_template}-[func]{RecordSolution}
[class]{preorder_traversal_iii_template}-[func]{IsValid}
[class]{preorder_traversal_iii_template}-[func]{MakeChoice}
[class]{preorder_traversal_iii_template}-[func]{UndoChoice}
[class]{preorder_traversal_iii_template}-[func]{Backtrack}
```
=== "Go"
```go title="preorder_traversal_iii_template.go"
[class]{}-[func]{isSolution}
[class]{}-[func]{recordSolution}
[class]{}-[func]{isValid}
[class]{}-[func]{makeChoice}
[class]{}-[func]{undoChoice}
[class]{}-[func]{backtrackIII}
```
=== "Swift"
```swift title="preorder_traversal_iii_template.swift"
[class]{}-[func]{isSolution}
[class]{}-[func]{recordSolution}
[class]{}-[func]{isValid}
[class]{}-[func]{makeChoice}
[class]{}-[func]{undoChoice}
[class]{}-[func]{backtrack}
```
=== "JS"
```javascript title="preorder_traversal_iii_template.js"
[class]{}-[func]{isSolution}
[class]{}-[func]{recordSolution}
[class]{}-[func]{isValid}
[class]{}-[func]{makeChoice}
[class]{}-[func]{undoChoice}
[class]{}-[func]{backtrack}
```
=== "TS"
```typescript title="preorder_traversal_iii_template.ts"
[class]{}-[func]{isSolution}
[class]{}-[func]{recordSolution}
[class]{}-[func]{isValid}
[class]{}-[func]{makeChoice}
[class]{}-[func]{undoChoice}
[class]{}-[func]{backtrack}
```
=== "Dart"
```dart title="preorder_traversal_iii_template.dart"
[class]{}-[func]{isSolution}
[class]{}-[func]{recordSolution}
[class]{}-[func]{isValid}
[class]{}-[func]{makeChoice}
[class]{}-[func]{undoChoice}
[class]{}-[func]{backtrack}
```
=== "Rust"
```rust title="preorder_traversal_iii_template.rs"
[class]{}-[func]{is_solution}
[class]{}-[func]{record_solution}
[class]{}-[func]{is_valid}
[class]{}-[func]{make_choice}
[class]{}-[func]{undo_choice}
[class]{}-[func]{backtrack}
```
=== "C"
```c title="preorder_traversal_iii_template.c"
[class]{}-[func]{isSolution}
[class]{}-[func]{recordSolution}
[class]{}-[func]{isValid}
[class]{}-[func]{makeChoice}
[class]{}-[func]{undoChoice}
[class]{}-[func]{backtrack}
```
=== "Zig"
```zig title="preorder_traversal_iii_template.zig"
[class]{}-[func]{isSolution}
[class]{}-[func]{recordSolution}
[class]{}-[func]{isValid}
[class]{}-[func]{makeChoice}
[class]{}-[func]{undoChoice}
[class]{}-[func]{backtrack}
```src
[file]{preorder_traversal_iii_template}-[class]{}-[func]{backtrack}
```
根据题意,我们在找到值为 $7$ 的节点后应该继续搜索,**因此需要将记录解之后的 `return` 语句删除**。下图对比了保留或删除 `return` 语句的搜索过程。

View file

@ -40,102 +40,8 @@
请注意,$n$ 维方阵中 $row - col$ 的范围是 $[-n + 1, n - 1]$ $row + col$ 的范围是 $[0, 2n - 2]$ ,所以主对角线和次对角线的数量都为 $2n - 1$ ,即数组 `diag1``diag2` 的长度都为 $2n - 1$ 。
=== "Python"
```python title="n_queens.py"
[class]{}-[func]{backtrack}
[class]{}-[func]{n_queens}
```
=== "C++"
```cpp title="n_queens.cpp"
[class]{}-[func]{backtrack}
[class]{}-[func]{nQueens}
```
=== "Java"
```java title="n_queens.java"
[class]{n_queens}-[func]{backtrack}
[class]{n_queens}-[func]{nQueens}
```
=== "C#"
```csharp title="n_queens.cs"
[class]{n_queens}-[func]{Backtrack}
[class]{n_queens}-[func]{NQueens}
```
=== "Go"
```go title="n_queens.go"
[class]{}-[func]{backtrack}
[class]{}-[func]{nQueens}
```
=== "Swift"
```swift title="n_queens.swift"
[class]{}-[func]{backtrack}
[class]{}-[func]{nQueens}
```
=== "JS"
```javascript title="n_queens.js"
[class]{}-[func]{backtrack}
[class]{}-[func]{nQueens}
```
=== "TS"
```typescript title="n_queens.ts"
[class]{}-[func]{backtrack}
[class]{}-[func]{nQueens}
```
=== "Dart"
```dart title="n_queens.dart"
[class]{}-[func]{backtrack}
[class]{}-[func]{nQueens}
```
=== "Rust"
```rust title="n_queens.rs"
[class]{}-[func]{backtrack}
[class]{}-[func]{n_queens}
```
=== "C"
```c title="n_queens.c"
[class]{result}-[func]{}
[class]{}-[func]{backtrack}
[class]{}-[func]{nQueens}
```
=== "Zig"
```zig title="n_queens.zig"
[class]{}-[func]{backtrack}
[class]{}-[func]{nQueens}
```src
[file]{n_queens}-[class]{}-[func]{n_queens}
```
逐行放置 $n$ 次,考虑列约束,则从第一行到最后一行分别有 $n$、$n-1$、$\dots$、$2$、$1$ 个选择,**因此时间复杂度为 $O(n!)$** 。实际上,根据对角线约束的剪枝也能够大幅地缩小搜索空间,因而搜索效率往往优于以上时间复杂度。

View file

@ -4,7 +4,7 @@
下表列举了几个示例数据,包括输入数组和对应的所有排列。
<p align="center"><id> &nbsp; 数组与链表的效率对比 </p>
<p align="center"><id> &nbsp; 全排列示例 </p>
| 输入数组 | 所有排列 |
| :---------- | :----------------------------------------------------------------- |
@ -43,100 +43,8 @@
想清楚以上信息之后,我们就可以在框架代码中做“完形填空”了。为了缩短代码行数,我们不单独实现框架代码中的各个函数,而是将他们展开在 `backtrack()` 函数中。
=== "Python"
```python title="permutations_i.py"
[class]{}-[func]{backtrack}
[class]{}-[func]{permutations_i}
```
=== "C++"
```cpp title="permutations_i.cpp"
[class]{}-[func]{backtrack}
[class]{}-[func]{permutationsI}
```
=== "Java"
```java title="permutations_i.java"
[class]{permutations_i}-[func]{backtrack}
[class]{permutations_i}-[func]{permutationsI}
```
=== "C#"
```csharp title="permutations_i.cs"
[class]{permutations_i}-[func]{Backtrack}
[class]{permutations_i}-[func]{PermutationsI}
```
=== "Go"
```go title="permutations_i.go"
[class]{}-[func]{backtrackI}
[class]{}-[func]{permutationsI}
```
=== "Swift"
```swift title="permutations_i.swift"
[class]{}-[func]{backtrack}
[class]{}-[func]{permutationsI}
```
=== "JS"
```javascript title="permutations_i.js"
[class]{}-[func]{backtrack}
[class]{}-[func]{permutationsI}
```
=== "TS"
```typescript title="permutations_i.ts"
[class]{}-[func]{backtrack}
[class]{}-[func]{permutationsI}
```
=== "Dart"
```dart title="permutations_i.dart"
[class]{}-[func]{backtrack}
[class]{}-[func]{permutationsI}
```
=== "Rust"
```rust title="permutations_i.rs"
[class]{}-[func]{backtrack}
[class]{}-[func]{permutations_i}
```
=== "C"
```c title="permutations_i.c"
[class]{}-[func]{backtrack}
[class]{}-[func]{permutationsI}
```
=== "Zig"
```zig title="permutations_i.zig"
[class]{}-[func]{backtrack}
[class]{}-[func]{permutationsI}
```src
[file]{permutations_i}-[class]{}-[func]{permutations_i}
```
## 考虑相等元素的情况
@ -167,100 +75,8 @@
在上一题的代码的基础上,我们考虑在每一轮选择中开启一个哈希表 `duplicated` ,用于记录该轮中已经尝试过的元素,并将重复元素剪枝。
=== "Python"
```python title="permutations_ii.py"
[class]{}-[func]{backtrack}
[class]{}-[func]{permutations_ii}
```
=== "C++"
```cpp title="permutations_ii.cpp"
[class]{}-[func]{backtrack}
[class]{}-[func]{permutationsII}
```
=== "Java"
```java title="permutations_ii.java"
[class]{permutations_ii}-[func]{backtrack}
[class]{permutations_ii}-[func]{permutationsII}
```
=== "C#"
```csharp title="permutations_ii.cs"
[class]{permutations_ii}-[func]{Backtrack}
[class]{permutations_ii}-[func]{PermutationsII}
```
=== "Go"
```go title="permutations_ii.go"
[class]{}-[func]{backtrackII}
[class]{}-[func]{permutationsII}
```
=== "Swift"
```swift title="permutations_ii.swift"
[class]{}-[func]{backtrack}
[class]{}-[func]{permutationsII}
```
=== "JS"
```javascript title="permutations_ii.js"
[class]{}-[func]{backtrack}
[class]{}-[func]{permutationsII}
```
=== "TS"
```typescript title="permutations_ii.ts"
[class]{}-[func]{backtrack}
[class]{}-[func]{permutationsII}
```
=== "Dart"
```dart title="permutations_ii.dart"
[class]{}-[func]{backtrack}
[class]{}-[func]{permutationsII}
```
=== "Rust"
```rust title="permutations_ii.rs"
[class]{}-[func]{backtrack}
[class]{}-[func]{permutations_ii}
```
=== "C"
```c title="permutations_ii.c"
[class]{}-[func]{backtrack}
[class]{}-[func]{permutationsII}
```
=== "Zig"
```zig title="permutations_ii.zig"
[class]{}-[func]{backtrack}
[class]{}-[func]{permutationsII}
```src
[file]{permutations_ii}-[class]{}-[func]{permutations_ii}
```
假设元素两两之间互不相同,则 $n$ 个元素共有 $n!$ 种排列(阶乘);在记录结果时,需要复制长度为 $n$ 的列表,使用 $O(n)$ 时间。**因此时间复杂度为 $O(n!n)$** 。

View file

@ -17,100 +17,8 @@
而与全排列问题不同的是,**本题集合中的元素可以被无限次选取**,因此无须借助 `selected` 布尔列表来记录元素是否已被选择。我们可以对全排列代码进行小幅修改,初步得到解题代码。
=== "Python"
```python title="subset_sum_i_naive.py"
[class]{}-[func]{backtrack}
[class]{}-[func]{subset_sum_i_naive}
```
=== "C++"
```cpp title="subset_sum_i_naive.cpp"
[class]{}-[func]{backtrack}
[class]{}-[func]{subsetSumINaive}
```
=== "Java"
```java title="subset_sum_i_naive.java"
[class]{subset_sum_i_naive}-[func]{backtrack}
[class]{subset_sum_i_naive}-[func]{subsetSumINaive}
```
=== "C#"
```csharp title="subset_sum_i_naive.cs"
[class]{subset_sum_i_naive}-[func]{Backtrack}
[class]{subset_sum_i_naive}-[func]{SubsetSumINaive}
```
=== "Go"
```go title="subset_sum_i_naive.go"
[class]{}-[func]{backtrackSubsetSumINaive}
[class]{}-[func]{subsetSumINaive}
```
=== "Swift"
```swift title="subset_sum_i_naive.swift"
[class]{}-[func]{backtrack}
[class]{}-[func]{subsetSumINaive}
```
=== "JS"
```javascript title="subset_sum_i_naive.js"
[class]{}-[func]{backtrack}
[class]{}-[func]{subsetSumINaive}
```
=== "TS"
```typescript title="subset_sum_i_naive.ts"
[class]{}-[func]{backtrack}
[class]{}-[func]{subsetSumINaive}
```
=== "Dart"
```dart title="subset_sum_i_naive.dart"
[class]{}-[func]{backtrack}
[class]{}-[func]{subsetSumINaive}
```
=== "Rust"
```rust title="subset_sum_i_naive.rs"
[class]{}-[func]{backtrack}
[class]{}-[func]{subset_sum_i_naive}
```
=== "C"
```c title="subset_sum_i_naive.c"
[class]{}-[func]{backtrack}
[class]{}-[func]{subsetSumINaive}
```
=== "Zig"
```zig title="subset_sum_i_naive.zig"
[class]{}-[func]{backtrack}
[class]{}-[func]{subsetSumINaive}
```src
[file]{subset_sum_i_naive}-[class]{}-[func]{subset_sum_i_naive}
```
向以上代码输入数组 $[3, 4, 5]$ 和目标元素 $9$ ,输出结果为 $[3, 3, 3], [4, 5], [5, 4]$ 。**虽然成功找出了所有和为 $9$ 的子集,但其中存在重复的子集 $[4, 5]$ 和 $[5, 4]$** 。
@ -150,100 +58,8 @@
- 在开启搜索前,先将数组 `nums` 排序。在遍历所有选择时,**当子集和超过 `target` 时直接结束循环**,因为后边的元素更大,其子集和都一定会超过 `target`
- 省去元素和变量 `total` **通过在 `target` 上执行减法来统计元素和**,当 `target` 等于 $0$ 时记录解。
=== "Python"
```python title="subset_sum_i.py"
[class]{}-[func]{backtrack}
[class]{}-[func]{subset_sum_i}
```
=== "C++"
```cpp title="subset_sum_i.cpp"
[class]{}-[func]{backtrack}
[class]{}-[func]{subsetSumI}
```
=== "Java"
```java title="subset_sum_i.java"
[class]{subset_sum_i}-[func]{backtrack}
[class]{subset_sum_i}-[func]{subsetSumI}
```
=== "C#"
```csharp title="subset_sum_i.cs"
[class]{subset_sum_i}-[func]{Backtrack}
[class]{subset_sum_i}-[func]{SubsetSumI}
```
=== "Go"
```go title="subset_sum_i.go"
[class]{}-[func]{backtrackSubsetSumI}
[class]{}-[func]{subsetSumI}
```
=== "Swift"
```swift title="subset_sum_i.swift"
[class]{}-[func]{backtrack}
[class]{}-[func]{subsetSumI}
```
=== "JS"
```javascript title="subset_sum_i.js"
[class]{}-[func]{backtrack}
[class]{}-[func]{subsetSumI}
```
=== "TS"
```typescript title="subset_sum_i.ts"
[class]{}-[func]{backtrack}
[class]{}-[func]{subsetSumI}
```
=== "Dart"
```dart title="subset_sum_i.dart"
[class]{}-[func]{backtrack}
[class]{}-[func]{subsetSumI}
```
=== "Rust"
```rust title="subset_sum_i.rs"
[class]{}-[func]{backtrack}
[class]{}-[func]{subset_sum_i}
```
=== "C"
```c title="subset_sum_i.c"
[class]{}-[func]{backtrack}
[class]{}-[func]{subsetSumI}
```
=== "Zig"
```zig title="subset_sum_i.zig"
[class]{}-[func]{backtrack}
[class]{}-[func]{subsetSumI}
```src
[file]{subset_sum_i}-[class]{}-[func]{subset_sum_i}
```
如下图所示,为将数组 $[3, 4, 5]$ 和目标元素 $9$ 输入到以上代码后的整体回溯过程。
@ -270,100 +86,8 @@
### 代码实现
=== "Python"
```python title="subset_sum_ii.py"
[class]{}-[func]{backtrack}
[class]{}-[func]{subset_sum_ii}
```
=== "C++"
```cpp title="subset_sum_ii.cpp"
[class]{}-[func]{backtrack}
[class]{}-[func]{subsetSumII}
```
=== "Java"
```java title="subset_sum_ii.java"
[class]{subset_sum_ii}-[func]{backtrack}
[class]{subset_sum_ii}-[func]{subsetSumII}
```
=== "C#"
```csharp title="subset_sum_ii.cs"
[class]{subset_sum_ii}-[func]{Backtrack}
[class]{subset_sum_ii}-[func]{SubsetSumII}
```
=== "Go"
```go title="subset_sum_ii.go"
[class]{}-[func]{backtrackSubsetSumII}
[class]{}-[func]{subsetSumII}
```
=== "Swift"
```swift title="subset_sum_ii.swift"
[class]{}-[func]{backtrack}
[class]{}-[func]{subsetSumII}
```
=== "JS"
```javascript title="subset_sum_ii.js"
[class]{}-[func]{backtrack}
[class]{}-[func]{subsetSumII}
```
=== "TS"
```typescript title="subset_sum_ii.ts"
[class]{}-[func]{backtrack}
[class]{}-[func]{subsetSumII}
```
=== "Dart"
```dart title="subset_sum_ii.dart"
[class]{}-[func]{backtrack}
[class]{}-[func]{subsetSumII}
```
=== "Rust"
```rust title="subset_sum_ii.rs"
[class]{}-[func]{backtrack}
[class]{}-[func]{subset_sum_ii}
```
=== "C"
```c title="subset_sum_ii.c"
[class]{}-[func]{backtrack}
[class]{}-[func]{subsetSumII}
```
=== "Zig"
```zig title="subset_sum_ii.zig"
[class]{}-[func]{backtrack}
[class]{}-[func]{subsetSumII}
```src
[file]{subset_sum_ii}-[class]{}-[func]{subset_sum_ii}
```
下图展示了数组 $[4, 4, 5]$ 和目标元素 $9$ 的回溯过程,共包含四种剪枝操作。请你将图示与代码注释相结合,理解整个搜索过程,以及每种剪枝操作是如何工作的。

View file

@ -12,76 +12,8 @@
以下函数基于 `for` 循环实现了求和 $1 + 2 + \dots + n$ ,求和结果使用变量 `res` 记录。需要注意的是Python 中 `range(a, b)` 对应的区间是“左闭右开”的,对应的遍历范围为 $a, a + 1, \dots, b-1$ 。
=== "Python"
```python title="iteration.py"
[class]{}-[func]{for_loop}
```
=== "C++"
```cpp title="iteration.cpp"
[class]{}-[func]{forLoop}
```
=== "Java"
```java title="iteration.java"
[class]{iteration}-[func]{forLoop}
```
=== "C#"
```csharp title="iteration.cs"
[class]{iteration}-[func]{ForLoop}
```
=== "Go"
```go title="iteration.go"
[class]{}-[func]{forLoop}
```
=== "Swift"
```swift title="iteration.swift"
[class]{}-[func]{forLoop}
```
=== "JS"
```javascript title="iteration.js"
[class]{}-[func]{forLoop}
```
=== "TS"
```typescript title="iteration.ts"
[class]{}-[func]{forLoop}
```
=== "Dart"
```dart title="iteration.dart"
[class]{}-[func]{forLoop}
```
=== "Rust"
```rust title="iteration.rs"
[class]{}-[func]{for_loop}
```
=== "C"
```c title="iteration.c"
[class]{}-[func]{forLoop}
```
=== "Zig"
```zig title="iteration.zig"
[class]{}-[func]{forLoop}
```src
[file]{iteration}-[class]{}-[func]{for_loop}
```
下图展示了该求和函数的流程框图。
@ -96,152 +28,16 @@
下面,我们用 `while` 循环来实现求和 $1 + 2 + \dots + n$ 。
=== "Python"
```python title="iteration.py"
[class]{}-[func]{while_loop}
```
=== "C++"
```cpp title="iteration.cpp"
[class]{}-[func]{whileLoop}
```
=== "Java"
```java title="iteration.java"
[class]{iteration}-[func]{whileLoop}
```
=== "C#"
```csharp title="iteration.cs"
[class]{iteration}-[func]{WhileLoop}
```
=== "Go"
```go title="iteration.go"
[class]{}-[func]{whileLoop}
```
=== "Swift"
```swift title="iteration.swift"
[class]{}-[func]{whileLoop}
```
=== "JS"
```javascript title="iteration.js"
[class]{}-[func]{whileLoop}
```
=== "TS"
```typescript title="iteration.ts"
[class]{}-[func]{whileLoop}
```
=== "Dart"
```dart title="iteration.dart"
[class]{}-[func]{whileLoop}
```
=== "Rust"
```rust title="iteration.rs"
[class]{}-[func]{while_loop}
```
=== "C"
```c title="iteration.c"
[class]{}-[func]{whileLoop}
```
=== "Zig"
```zig title="iteration.zig"
[class]{}-[func]{whileLoop}
```src
[file]{iteration}-[class]{}-[func]{while_loop}
```
`while` 循环中,由于初始化和更新条件变量的步骤是独立在循环结构之外的,**因此它比 `for` 循环的自由度更高**。
例如在以下代码中,条件变量 $i$ 每轮进行了两次更新,这种情况就不太方便用 `for` 循环实现。
=== "Python"
```python title="iteration.py"
[class]{}-[func]{while_loop_ii}
```
=== "C++"
```cpp title="iteration.cpp"
[class]{}-[func]{whileLoopII}
```
=== "Java"
```java title="iteration.java"
[class]{iteration}-[func]{whileLoopII}
```
=== "C#"
```csharp title="iteration.cs"
[class]{iteration}-[func]{WhileLoopII}
```
=== "Go"
```go title="iteration.go"
[class]{}-[func]{whileLoopII}
```
=== "Swift"
```swift title="iteration.swift"
[class]{}-[func]{whileLoopII}
```
=== "JS"
```javascript title="iteration.js"
[class]{}-[func]{whileLoopII}
```
=== "TS"
```typescript title="iteration.ts"
[class]{}-[func]{whileLoopII}
```
=== "Dart"
```dart title="iteration.dart"
[class]{}-[func]{whileLoopII}
```
=== "Rust"
```rust title="iteration.rs"
[class]{}-[func]{while_loop_ii}
```
=== "C"
```c title="iteration.c"
[class]{}-[func]{whileLoopII}
```
=== "Zig"
```zig title="iteration.zig"
[class]{}-[func]{whileLoopII}
```src
[file]{iteration}-[class]{}-[func]{while_loop_ii}
```
总的来说,**`for` 循环的代码更加紧凑,`while` 循环更加灵活**,两者都可以实现迭代结构。选择使用哪一个应该根据特定问题的需求来决定。
@ -250,76 +46,8 @@
我们可以在一个循环结构内嵌套另一个循环结构,以 `for` 循环为例:
=== "Python"
```python title="iteration.py"
[class]{}-[func]{nested_for_loop}
```
=== "C++"
```cpp title="iteration.cpp"
[class]{}-[func]{nestedForLoop}
```
=== "Java"
```java title="iteration.java"
[class]{iteration}-[func]{nestedForLoop}
```
=== "C#"
```csharp title="iteration.cs"
[class]{iteration}-[func]{NestedForLoop}
```
=== "Go"
```go title="iteration.go"
[class]{}-[func]{nestedForLoop}
```
=== "Swift"
```swift title="iteration.swift"
[class]{}-[func]{nestedForLoop}
```
=== "JS"
```javascript title="iteration.js"
[class]{}-[func]{nestedForLoop}
```
=== "TS"
```typescript title="iteration.ts"
[class]{}-[func]{nestedForLoop}
```
=== "Dart"
```dart title="iteration.dart"
[class]{}-[func]{nestedForLoop}
```
=== "Rust"
```rust title="iteration.rs"
[class]{}-[func]{nested_for_loop}
```
=== "C"
```c title="iteration.c"
[class]{}-[func]{nestedForLoop}
```
=== "Zig"
```zig title="iteration.zig"
[class]{}-[func]{nestedForLoop}
```src
[file]{iteration}-[class]{}-[func]{nested_for_loop}
```
下图给出了该嵌套循环的流程框图。
@ -345,76 +73,8 @@
观察以下代码,我们只需调用函数 `recur(n)` ,就可以完成 $1 + 2 + \dots + n$ 的计算:
=== "Python"
```python title="recursion.py"
[class]{}-[func]{recur}
```
=== "C++"
```cpp title="recursion.cpp"
[class]{}-[func]{recur}
```
=== "Java"
```java title="recursion.java"
[class]{recursion}-[func]{recur}
```
=== "C#"
```csharp title="recursion.cs"
[class]{recursion}-[func]{Recur}
```
=== "Go"
```go title="recursion.go"
[class]{}-[func]{recur}
```
=== "Swift"
```swift title="recursion.swift"
[class]{}-[func]{recur}
```
=== "JS"
```javascript title="recursion.js"
[class]{}-[func]{recur}
```
=== "TS"
```typescript title="recursion.ts"
[class]{}-[func]{recur}
```
=== "Dart"
```dart title="recursion.dart"
[class]{}-[func]{recur}
```
=== "Rust"
```rust title="recursion.rs"
[class]{}-[func]{recur}
```
=== "C"
```c title="recursion.c"
[class]{}-[func]{recur}
```
=== "Zig"
```zig title="recursion.zig"
[class]{}-[func]{recur}
```src
[file]{recursion}-[class]{}-[func]{recur}
```
下图展示了该函数的递归过程。
@ -453,76 +113,8 @@
以计算 $1 + 2 + \dots + n$ 为例,我们可以将结果变量 `res` 设为函数参数,从而实现尾递归。
=== "Python"
```python title="recursion.py"
[class]{}-[func]{tail_recur}
```
=== "C++"
```cpp title="recursion.cpp"
[class]{}-[func]{tailRecur}
```
=== "Java"
```java title="recursion.java"
[class]{recursion}-[func]{tailRecur}
```
=== "C#"
```csharp title="recursion.cs"
[class]{recursion}-[func]{TailRecur}
```
=== "Go"
```go title="recursion.go"
[class]{}-[func]{tailRecur}
```
=== "Swift"
```swift title="recursion.swift"
[class]{}-[func]{tailRecur}
```
=== "JS"
```javascript title="recursion.js"
[class]{}-[func]{tailRecur}
```
=== "TS"
```typescript title="recursion.ts"
[class]{}-[func]{tailRecur}
```
=== "Dart"
```dart title="recursion.dart"
[class]{}-[func]{tailRecur}
```
=== "Rust"
```rust title="recursion.rs"
[class]{}-[func]{tail_recur}
```
=== "C"
```c title="recursion.c"
[class]{}-[func]{tailRecur}
```
=== "Zig"
```zig title="recursion.zig"
[class]{}-[func]{tailRecur}
```src
[file]{recursion}-[class]{}-[func]{tail_recur}
```
尾递归的执行过程如下图所示。对比普通递归和尾递归,求和操作的执行点是不同的。
@ -551,76 +143,8 @@
按照递推关系进行递归调用,将前两个数字作为终止条件,便可写出递归代码。调用 `fib(n)` 即可得到斐波那契数列的第 $n$ 个数字。
=== "Python"
```python title="recursion.py"
[class]{}-[func]{fib}
```
=== "C++"
```cpp title="recursion.cpp"
[class]{}-[func]{fib}
```
=== "Java"
```java title="recursion.java"
[class]{recursion}-[func]{fib}
```
=== "C#"
```csharp title="recursion.cs"
[class]{recursion}-[func]{Fib}
```
=== "Go"
```go title="recursion.go"
[class]{}-[func]{fib}
```
=== "Swift"
```swift title="recursion.swift"
[class]{}-[func]{fib}
```
=== "JS"
```javascript title="recursion.js"
[class]{}-[func]{fib}
```
=== "TS"
```typescript title="recursion.ts"
[class]{}-[func]{fib}
```
=== "Dart"
```dart title="recursion.dart"
[class]{}-[func]{fib}
```
=== "Rust"
```rust title="recursion.rs"
[class]{}-[func]{fib}
```
=== "C"
```c title="recursion.c"
[class]{}-[func]{fib}
```
=== "Zig"
```zig title="recursion.zig"
[class]{}-[func]{fib}
```src
[file]{recursion}-[class]{}-[func]{fib}
```
观察以上代码,我们在函数内递归调用了两个函数,**这意味着从一个调用产生了两个调用分支**。如下图所示,这样不断递归调用下去,最终将产生一个层数为 $n$ 的「递归树 recursion tree」。
@ -658,76 +182,8 @@
因此,**我们可以使用一个显式的栈来模拟调用栈的行为**,从而将递归转化为迭代形式:
=== "Python"
```python title="recursion.py"
[class]{}-[func]{for_loop_recur}
```
=== "C++"
```cpp title="recursion.cpp"
[class]{}-[func]{forLoopRecur}
```
=== "Java"
```java title="recursion.java"
[class]{recursion}-[func]{forLoopRecur}
```
=== "C#"
```csharp title="recursion.cs"
[class]{recursion}-[func]{ForLoopRecur}
```
=== "Go"
```go title="recursion.go"
[class]{}-[func]{forLoopRecur}
```
=== "Swift"
```swift title="recursion.swift"
[class]{}-[func]{forLoopRecur}
```
=== "JS"
```javascript title="recursion.js"
[class]{}-[func]{forLoopRecur}
```
=== "TS"
```typescript title="recursion.ts"
[class]{}-[func]{forLoopRecur}
```
=== "Dart"
```dart title="recursion.dart"
[class]{}-[func]{forLoopRecur}
```
=== "Rust"
```rust title="recursion.rs"
[class]{}-[func]{for_loop_recur}
```
=== "C"
```c title="recursion.c"
[class]{}-[func]{forLoopRecur}
```
=== "Zig"
```zig title="recursion.zig"
[class]{}-[func]{forLoopRecur}
```src
[file]{recursion}-[class]{}-[func]{for_loop_recur}
```
观察以上代码,当递归被转换为迭代后,代码变得更加复杂了。尽管迭代和递归在很多情况下可以互相转换,但也不一定值得这样做,有以下两点原因。

View file

@ -719,252 +719,22 @@ $$
需要注意的是,在循环中初始化变量或调用函数而占用的内存,在进入下一循环后就会被释放,因此不会累积占用空间,空间复杂度仍为 $O(1)$
=== "Python"
```python title="space_complexity.py"
[class]{}-[func]{function}
[class]{}-[func]{constant}
```
=== "C++"
```cpp title="space_complexity.cpp"
[class]{}-[func]{func}
[class]{}-[func]{constant}
```
=== "Java"
```java title="space_complexity.java"
[class]{space_complexity}-[func]{function}
[class]{space_complexity}-[func]{constant}
```
=== "C#"
```csharp title="space_complexity.cs"
[class]{space_complexity}-[func]{Function}
[class]{space_complexity}-[func]{Constant}
```
=== "Go"
```go title="space_complexity.go"
[class]{}-[func]{function}
[class]{}-[func]{spaceConstant}
```
=== "Swift"
```swift title="space_complexity.swift"
[class]{}-[func]{function}
[class]{}-[func]{constant}
```
=== "JS"
```javascript title="space_complexity.js"
[class]{}-[func]{constFunc}
[class]{}-[func]{constant}
```
=== "TS"
```typescript title="space_complexity.ts"
[class]{}-[func]{constFunc}
[class]{}-[func]{constant}
```
=== "Dart"
```dart title="space_complexity.dart"
[class]{}-[func]{function}
[class]{}-[func]{constant}
```
=== "Rust"
```rust title="space_complexity.rs"
[class]{}-[func]{function}
[class]{}-[func]{constant}
```
=== "C"
```c title="space_complexity.c"
[class]{}-[func]{func}
[class]{}-[func]{constant}
```
=== "Zig"
```zig title="space_complexity.zig"
[class]{}-[func]{function}
[class]{}-[func]{constant}
```src
[file]{space_complexity}-[class]{}-[func]{constant}
```
### 线性阶 $O(n)$
线性阶常见于元素数量与 $n$ 成正比的数组、链表、栈、队列等:
=== "Python"
```python title="space_complexity.py"
[class]{}-[func]{linear}
```
=== "C++"
```cpp title="space_complexity.cpp"
[class]{}-[func]{linear}
```
=== "Java"
```java title="space_complexity.java"
[class]{space_complexity}-[func]{linear}
```
=== "C#"
```csharp title="space_complexity.cs"
[class]{space_complexity}-[func]{Linear}
```
=== "Go"
```go title="space_complexity.go"
[class]{}-[func]{spaceLinear}
```
=== "Swift"
```swift title="space_complexity.swift"
[class]{}-[func]{linear}
```
=== "JS"
```javascript title="space_complexity.js"
[class]{}-[func]{linear}
```
=== "TS"
```typescript title="space_complexity.ts"
[class]{}-[func]{linear}
```
=== "Dart"
```dart title="space_complexity.dart"
[class]{}-[func]{linear}
```
=== "Rust"
```rust title="space_complexity.rs"
[class]{}-[func]{linear}
```
=== "C"
```c title="space_complexity.c"
[class]{hashTable}-[func]{}
[class]{}-[func]{linear}
```
=== "Zig"
```zig title="space_complexity.zig"
[class]{}-[func]{linear}
```src
[file]{space_complexity}-[class]{}-[func]{linear}
```
如下图所示,此函数的递归深度为 $n$ ,即同时存在 $n$ 个未返回的 `linear_recur()` 函数,使用 $O(n)$ 大小的栈帧空间:
=== "Python"
```python title="space_complexity.py"
[class]{}-[func]{linear_recur}
```
=== "C++"
```cpp title="space_complexity.cpp"
[class]{}-[func]{linearRecur}
```
=== "Java"
```java title="space_complexity.java"
[class]{space_complexity}-[func]{linearRecur}
```
=== "C#"
```csharp title="space_complexity.cs"
[class]{space_complexity}-[func]{LinearRecur}
```
=== "Go"
```go title="space_complexity.go"
[class]{}-[func]{spaceLinearRecur}
```
=== "Swift"
```swift title="space_complexity.swift"
[class]{}-[func]{linearRecur}
```
=== "JS"
```javascript title="space_complexity.js"
[class]{}-[func]{linearRecur}
```
=== "TS"
```typescript title="space_complexity.ts"
[class]{}-[func]{linearRecur}
```
=== "Dart"
```dart title="space_complexity.dart"
[class]{}-[func]{linearRecur}
```
=== "Rust"
```rust title="space_complexity.rs"
[class]{}-[func]{linear_recur}
```
=== "C"
```c title="space_complexity.c"
[class]{}-[func]{linearRecur}
```
=== "Zig"
```zig title="space_complexity.zig"
[class]{}-[func]{linearRecur}
```src
[file]{space_complexity}-[class]{}-[func]{linear_recur}
```
![递归函数产生的线性阶空间复杂度](space_complexity.assets/space_complexity_recursive_linear.png)
@ -973,150 +743,14 @@ $$
平方阶常见于矩阵和图,元素数量与 $n$ 成平方关系:
=== "Python"
```python title="space_complexity.py"
[class]{}-[func]{quadratic}
```
=== "C++"
```cpp title="space_complexity.cpp"
[class]{}-[func]{quadratic}
```
=== "Java"
```java title="space_complexity.java"
[class]{space_complexity}-[func]{quadratic}
```
=== "C#"
```csharp title="space_complexity.cs"
[class]{space_complexity}-[func]{Quadratic}
```
=== "Go"
```go title="space_complexity.go"
[class]{}-[func]{spaceQuadratic}
```
=== "Swift"
```swift title="space_complexity.swift"
[class]{}-[func]{quadratic}
```
=== "JS"
```javascript title="space_complexity.js"
[class]{}-[func]{quadratic}
```
=== "TS"
```typescript title="space_complexity.ts"
[class]{}-[func]{quadratic}
```
=== "Dart"
```dart title="space_complexity.dart"
[class]{}-[func]{quadratic}
```
=== "Rust"
```rust title="space_complexity.rs"
[class]{}-[func]{quadratic}
```
=== "C"
```c title="space_complexity.c"
[class]{}-[func]{quadratic}
```
=== "Zig"
```zig title="space_complexity.zig"
[class]{}-[func]{quadratic}
```src
[file]{space_complexity}-[class]{}-[func]{quadratic}
```
如下图所示,该函数的递归深度为 $n$ ,在每个递归函数中都初始化了一个数组,长度分别为 $n$、$n-1$、$\dots$、$2$、$1$ ,平均长度为 $n / 2$ ,因此总体占用 $O(n^2)$ 空间:
=== "Python"
```python title="space_complexity.py"
[class]{}-[func]{quadratic_recur}
```
=== "C++"
```cpp title="space_complexity.cpp"
[class]{}-[func]{quadraticRecur}
```
=== "Java"
```java title="space_complexity.java"
[class]{space_complexity}-[func]{quadraticRecur}
```
=== "C#"
```csharp title="space_complexity.cs"
[class]{space_complexity}-[func]{QuadraticRecur}
```
=== "Go"
```go title="space_complexity.go"
[class]{}-[func]{spaceQuadraticRecur}
```
=== "Swift"
```swift title="space_complexity.swift"
[class]{}-[func]{quadraticRecur}
```
=== "JS"
```javascript title="space_complexity.js"
[class]{}-[func]{quadraticRecur}
```
=== "TS"
```typescript title="space_complexity.ts"
[class]{}-[func]{quadraticRecur}
```
=== "Dart"
```dart title="space_complexity.dart"
[class]{}-[func]{quadraticRecur}
```
=== "Rust"
```rust title="space_complexity.rs"
[class]{}-[func]{quadratic_recur}
```
=== "C"
```c title="space_complexity.c"
[class]{}-[func]{quadraticRecur}
```
=== "Zig"
```zig title="space_complexity.zig"
[class]{}-[func]{quadraticRecur}
```src
[file]{space_complexity}-[class]{}-[func]{quadratic_recur}
```
![递归函数产生的平方阶空间复杂度](space_complexity.assets/space_complexity_recursive_quadratic.png)
@ -1125,76 +759,8 @@ $$
指数阶常见于二叉树。观察下图,高度为 $n$ 的“满二叉树”的节点数量为 $2^n - 1$ ,占用 $O(2^n)$ 空间:
=== "Python"
```python title="space_complexity.py"
[class]{}-[func]{build_tree}
```
=== "C++"
```cpp title="space_complexity.cpp"
[class]{}-[func]{buildTree}
```
=== "Java"
```java title="space_complexity.java"
[class]{space_complexity}-[func]{buildTree}
```
=== "C#"
```csharp title="space_complexity.cs"
[class]{space_complexity}-[func]{BuildTree}
```
=== "Go"
```go title="space_complexity.go"
[class]{}-[func]{buildTree}
```
=== "Swift"
```swift title="space_complexity.swift"
[class]{}-[func]{buildTree}
```
=== "JS"
```javascript title="space_complexity.js"
[class]{}-[func]{buildTree}
```
=== "TS"
```typescript title="space_complexity.ts"
[class]{}-[func]{buildTree}
```
=== "Dart"
```dart title="space_complexity.dart"
[class]{}-[func]{buildTree}
```
=== "Rust"
```rust title="space_complexity.rs"
[class]{}-[func]{build_tree}
```
=== "C"
```c title="space_complexity.c"
[class]{}-[func]{buildTree}
```
=== "Zig"
```zig title="space_complexity.zig"
[class]{}-[func]{buildTree}
```src
[file]{space_complexity}-[class]{}-[func]{build_tree}
```
![满二叉树产生的指数阶空间复杂度](space_complexity.assets/space_complexity_exponential.png)

View file

@ -897,226 +897,22 @@ $$
在以下函数中,尽管操作数量 `size` 可能很大,但由于其与输入数据大小 $n$ 无关,因此时间复杂度仍为 $O(1)$
=== "Python"
```python title="time_complexity.py"
[class]{}-[func]{constant}
```
=== "C++"
```cpp title="time_complexity.cpp"
[class]{}-[func]{constant}
```
=== "Java"
```java title="time_complexity.java"
[class]{time_complexity}-[func]{constant}
```
=== "C#"
```csharp title="time_complexity.cs"
[class]{time_complexity}-[func]{Constant}
```
=== "Go"
```go title="time_complexity.go"
[class]{}-[func]{constant}
```
=== "Swift"
```swift title="time_complexity.swift"
[class]{}-[func]{constant}
```
=== "JS"
```javascript title="time_complexity.js"
[class]{}-[func]{constant}
```
=== "TS"
```typescript title="time_complexity.ts"
[class]{}-[func]{constant}
```
=== "Dart"
```dart title="time_complexity.dart"
[class]{}-[func]{constant}
```
=== "Rust"
```rust title="time_complexity.rs"
[class]{}-[func]{constant}
```
=== "C"
```c title="time_complexity.c"
[class]{}-[func]{constant}
```
=== "Zig"
```zig title="time_complexity.zig"
[class]{}-[func]{constant}
```src
[file]{time_complexity}-[class]{}-[func]{constant}
```
### 线性阶 $O(n)$
线性阶的操作数量相对于输入数据大小 $n$ 以线性级别增长。线性阶通常出现在单层循环中:
=== "Python"
```python title="time_complexity.py"
[class]{}-[func]{linear}
```
=== "C++"
```cpp title="time_complexity.cpp"
[class]{}-[func]{linear}
```
=== "Java"
```java title="time_complexity.java"
[class]{time_complexity}-[func]{linear}
```
=== "C#"
```csharp title="time_complexity.cs"
[class]{time_complexity}-[func]{Linear}
```
=== "Go"
```go title="time_complexity.go"
[class]{}-[func]{linear}
```
=== "Swift"
```swift title="time_complexity.swift"
[class]{}-[func]{linear}
```
=== "JS"
```javascript title="time_complexity.js"
[class]{}-[func]{linear}
```
=== "TS"
```typescript title="time_complexity.ts"
[class]{}-[func]{linear}
```
=== "Dart"
```dart title="time_complexity.dart"
[class]{}-[func]{linear}
```
=== "Rust"
```rust title="time_complexity.rs"
[class]{}-[func]{linear}
```
=== "C"
```c title="time_complexity.c"
[class]{}-[func]{linear}
```
=== "Zig"
```zig title="time_complexity.zig"
[class]{}-[func]{linear}
```src
[file]{time_complexity}-[class]{}-[func]{linear}
```
遍历数组和遍历链表等操作的时间复杂度均为 $O(n)$ ,其中 $n$ 为数组或链表的长度:
=== "Python"
```python title="time_complexity.py"
[class]{}-[func]{array_traversal}
```
=== "C++"
```cpp title="time_complexity.cpp"
[class]{}-[func]{arrayTraversal}
```
=== "Java"
```java title="time_complexity.java"
[class]{time_complexity}-[func]{arrayTraversal}
```
=== "C#"
```csharp title="time_complexity.cs"
[class]{time_complexity}-[func]{ArrayTraversal}
```
=== "Go"
```go title="time_complexity.go"
[class]{}-[func]{arrayTraversal}
```
=== "Swift"
```swift title="time_complexity.swift"
[class]{}-[func]{arrayTraversal}
```
=== "JS"
```javascript title="time_complexity.js"
[class]{}-[func]{arrayTraversal}
```
=== "TS"
```typescript title="time_complexity.ts"
[class]{}-[func]{arrayTraversal}
```
=== "Dart"
```dart title="time_complexity.dart"
[class]{}-[func]{arrayTraversal}
```
=== "Rust"
```rust title="time_complexity.rs"
[class]{}-[func]{array_traversal}
```
=== "C"
```c title="time_complexity.c"
[class]{}-[func]{arrayTraversal}
```
=== "Zig"
```zig title="time_complexity.zig"
[class]{}-[func]{arrayTraversal}
```src
[file]{time_complexity}-[class]{}-[func]{array_traversal}
```
值得注意的是,**输入数据大小 $n$ 需根据输入数据的类型来具体确定**。比如在第一个示例中,变量 $n$ 为输入数据大小;在第二个示例中,数组长度 $n$ 为数据大小。
@ -1125,76 +921,8 @@ $$
平方阶的操作数量相对于输入数据大小 $n$ 以平方级别增长。平方阶通常出现在嵌套循环中,外层循环和内层循环都为 $O(n)$ ,因此总体为 $O(n^2)$
=== "Python"
```python title="time_complexity.py"
[class]{}-[func]{quadratic}
```
=== "C++"
```cpp title="time_complexity.cpp"
[class]{}-[func]{quadratic}
```
=== "Java"
```java title="time_complexity.java"
[class]{time_complexity}-[func]{quadratic}
```
=== "C#"
```csharp title="time_complexity.cs"
[class]{time_complexity}-[func]{Quadratic}
```
=== "Go"
```go title="time_complexity.go"
[class]{}-[func]{quadratic}
```
=== "Swift"
```swift title="time_complexity.swift"
[class]{}-[func]{quadratic}
```
=== "JS"
```javascript title="time_complexity.js"
[class]{}-[func]{quadratic}
```
=== "TS"
```typescript title="time_complexity.ts"
[class]{}-[func]{quadratic}
```
=== "Dart"
```dart title="time_complexity.dart"
[class]{}-[func]{quadratic}
```
=== "Rust"
```rust title="time_complexity.rs"
[class]{}-[func]{quadratic}
```
=== "C"
```c title="time_complexity.c"
[class]{}-[func]{quadratic}
```
=== "Zig"
```zig title="time_complexity.zig"
[class]{}-[func]{quadratic}
```src
[file]{time_complexity}-[class]{}-[func]{quadratic}
```
下图对比了常数阶、线性阶和平方阶三种时间复杂度。
@ -1203,76 +931,8 @@ $$
以冒泡排序为例,外层循环执行 $n - 1$ 次,内层循环执行 $n-1$、$n-2$、$\dots$、$2$、$1$ 次,平均为 $n / 2$ 次,因此时间复杂度为 $O((n - 1) n / 2) = O(n^2)$ 。
=== "Python"
```python title="time_complexity.py"
[class]{}-[func]{bubble_sort}
```
=== "C++"
```cpp title="time_complexity.cpp"
[class]{}-[func]{bubbleSort}
```
=== "Java"
```java title="time_complexity.java"
[class]{time_complexity}-[func]{bubbleSort}
```
=== "C#"
```csharp title="time_complexity.cs"
[class]{time_complexity}-[func]{BubbleSort}
```
=== "Go"
```go title="time_complexity.go"
[class]{}-[func]{bubbleSort}
```
=== "Swift"
```swift title="time_complexity.swift"
[class]{}-[func]{bubbleSort}
```
=== "JS"
```javascript title="time_complexity.js"
[class]{}-[func]{bubbleSort}
```
=== "TS"
```typescript title="time_complexity.ts"
[class]{}-[func]{bubbleSort}
```
=== "Dart"
```dart title="time_complexity.dart"
[class]{}-[func]{bubbleSort}
```
=== "Rust"
```rust title="time_complexity.rs"
[class]{}-[func]{bubble_sort}
```
=== "C"
```c title="time_complexity.c"
[class]{}-[func]{bubbleSort}
```
=== "Zig"
```zig title="time_complexity.zig"
[class]{}-[func]{bubbleSort}
```src
[file]{time_complexity}-[class]{}-[func]{bubble_sort}
```
### 指数阶 $O(2^n)$
@ -1281,152 +941,16 @@ $$
下图和以下代码模拟了细胞分裂的过程,时间复杂度为 $O(2^n)$ 。
=== "Python"
```python title="time_complexity.py"
[class]{}-[func]{exponential}
```
=== "C++"
```cpp title="time_complexity.cpp"
[class]{}-[func]{exponential}
```
=== "Java"
```java title="time_complexity.java"
[class]{time_complexity}-[func]{exponential}
```
=== "C#"
```csharp title="time_complexity.cs"
[class]{time_complexity}-[func]{Exponential}
```
=== "Go"
```go title="time_complexity.go"
[class]{}-[func]{exponential}
```
=== "Swift"
```swift title="time_complexity.swift"
[class]{}-[func]{exponential}
```
=== "JS"
```javascript title="time_complexity.js"
[class]{}-[func]{exponential}
```
=== "TS"
```typescript title="time_complexity.ts"
[class]{}-[func]{exponential}
```
=== "Dart"
```dart title="time_complexity.dart"
[class]{}-[func]{exponential}
```
=== "Rust"
```rust title="time_complexity.rs"
[class]{}-[func]{exponential}
```
=== "C"
```c title="time_complexity.c"
[class]{}-[func]{exponential}
```
=== "Zig"
```zig title="time_complexity.zig"
[class]{}-[func]{exponential}
```src
[file]{time_complexity}-[class]{}-[func]{exponential}
```
![指数阶的时间复杂度](time_complexity.assets/time_complexity_exponential.png)
在实际算法中,指数阶常出现于递归函数中。例如在以下代码中,其递归地一分为二,经过 $n$ 次分裂后停止:
=== "Python"
```python title="time_complexity.py"
[class]{}-[func]{exp_recur}
```
=== "C++"
```cpp title="time_complexity.cpp"
[class]{}-[func]{expRecur}
```
=== "Java"
```java title="time_complexity.java"
[class]{time_complexity}-[func]{expRecur}
```
=== "C#"
```csharp title="time_complexity.cs"
[class]{time_complexity}-[func]{ExpRecur}
```
=== "Go"
```go title="time_complexity.go"
[class]{}-[func]{expRecur}
```
=== "Swift"
```swift title="time_complexity.swift"
[class]{}-[func]{expRecur}
```
=== "JS"
```javascript title="time_complexity.js"
[class]{}-[func]{expRecur}
```
=== "TS"
```typescript title="time_complexity.ts"
[class]{}-[func]{expRecur}
```
=== "Dart"
```dart title="time_complexity.dart"
[class]{}-[func]{expRecur}
```
=== "Rust"
```rust title="time_complexity.rs"
[class]{}-[func]{exp_recur}
```
=== "C"
```c title="time_complexity.c"
[class]{}-[func]{expRecur}
```
=== "Zig"
```zig title="time_complexity.zig"
[class]{}-[func]{expRecur}
```src
[file]{time_complexity}-[class]{}-[func]{exp_recur}
```
指数阶增长非常迅速,在穷举法(暴力搜索、回溯等)中比较常见。对于数据规模较大的问题,指数阶是不可接受的,通常需要使用动态规划或贪心等算法来解决。
@ -1437,152 +961,16 @@ $$
下图和以下代码模拟了“每轮缩减到一半”的过程,时间复杂度为 $O(\log_2 n)$ ,简记为 $O(\log n)$ 。
=== "Python"
```python title="time_complexity.py"
[class]{}-[func]{logarithmic}
```
=== "C++"
```cpp title="time_complexity.cpp"
[class]{}-[func]{logarithmic}
```
=== "Java"
```java title="time_complexity.java"
[class]{time_complexity}-[func]{logarithmic}
```
=== "C#"
```csharp title="time_complexity.cs"
[class]{time_complexity}-[func]{Logarithmic}
```
=== "Go"
```go title="time_complexity.go"
[class]{}-[func]{logarithmic}
```
=== "Swift"
```swift title="time_complexity.swift"
[class]{}-[func]{logarithmic}
```
=== "JS"
```javascript title="time_complexity.js"
[class]{}-[func]{logarithmic}
```
=== "TS"
```typescript title="time_complexity.ts"
[class]{}-[func]{logarithmic}
```
=== "Dart"
```dart title="time_complexity.dart"
[class]{}-[func]{logarithmic}
```
=== "Rust"
```rust title="time_complexity.rs"
[class]{}-[func]{logarithmic}
```
=== "C"
```c title="time_complexity.c"
[class]{}-[func]{logarithmic}
```
=== "Zig"
```zig title="time_complexity.zig"
[class]{}-[func]{logarithmic}
```src
[file]{time_complexity}-[class]{}-[func]{logarithmic}
```
![对数阶的时间复杂度](time_complexity.assets/time_complexity_logarithmic.png)
与指数阶类似,对数阶也常出现于递归函数中。以下代码形成了一个高度为 $\log_2 n$ 的递归树:
=== "Python"
```python title="time_complexity.py"
[class]{}-[func]{log_recur}
```
=== "C++"
```cpp title="time_complexity.cpp"
[class]{}-[func]{logRecur}
```
=== "Java"
```java title="time_complexity.java"
[class]{time_complexity}-[func]{logRecur}
```
=== "C#"
```csharp title="time_complexity.cs"
[class]{time_complexity}-[func]{LogRecur}
```
=== "Go"
```go title="time_complexity.go"
[class]{}-[func]{logRecur}
```
=== "Swift"
```swift title="time_complexity.swift"
[class]{}-[func]{logRecur}
```
=== "JS"
```javascript title="time_complexity.js"
[class]{}-[func]{logRecur}
```
=== "TS"
```typescript title="time_complexity.ts"
[class]{}-[func]{logRecur}
```
=== "Dart"
```dart title="time_complexity.dart"
[class]{}-[func]{logRecur}
```
=== "Rust"
```rust title="time_complexity.rs"
[class]{}-[func]{log_recur}
```
=== "C"
```c title="time_complexity.c"
[class]{}-[func]{logRecur}
```
=== "Zig"
```zig title="time_complexity.zig"
[class]{}-[func]{logRecur}
```src
[file]{time_complexity}-[class]{}-[func]{log_recur}
```
对数阶常出现于基于分治策略的算法中,体现了“一分为多”和“化繁为简”的算法思想。它增长缓慢,是仅次于常数阶的理想的时间复杂度。
@ -1601,76 +989,8 @@ $$
线性对数阶常出现于嵌套循环中,两层循环的时间复杂度分别为 $O(\log n)$ 和 $O(n)$ 。相关代码如下:
=== "Python"
```python title="time_complexity.py"
[class]{}-[func]{linear_log_recur}
```
=== "C++"
```cpp title="time_complexity.cpp"
[class]{}-[func]{linearLogRecur}
```
=== "Java"
```java title="time_complexity.java"
[class]{time_complexity}-[func]{linearLogRecur}
```
=== "C#"
```csharp title="time_complexity.cs"
[class]{time_complexity}-[func]{LinearLogRecur}
```
=== "Go"
```go title="time_complexity.go"
[class]{}-[func]{linearLogRecur}
```
=== "Swift"
```swift title="time_complexity.swift"
[class]{}-[func]{linearLogRecur}
```
=== "JS"
```javascript title="time_complexity.js"
[class]{}-[func]{linearLogRecur}
```
=== "TS"
```typescript title="time_complexity.ts"
[class]{}-[func]{linearLogRecur}
```
=== "Dart"
```dart title="time_complexity.dart"
[class]{}-[func]{linearLogRecur}
```
=== "Rust"
```rust title="time_complexity.rs"
[class]{}-[func]{linear_log_recur}
```
=== "C"
```c title="time_complexity.c"
[class]{}-[func]{linearLogRecur}
```
=== "Zig"
```zig title="time_complexity.zig"
[class]{}-[func]{linearLogRecur}
```src
[file]{time_complexity}-[class]{}-[func]{linear_log_recur}
```
下图展示了线性对数阶的生成方式。二叉树的每一层的操作总数都为 $n$ ,树共有 $\log_2 n + 1$ 层,因此时间复杂度为 $O(n \log n)$ 。
@ -1689,76 +1009,8 @@ $$
阶乘通常使用递归实现。如下图和以下代码所示,第一层分裂出 $n$ 个,第二层分裂出 $n - 1$ 个,以此类推,直至第 $n$ 层时停止分裂:
=== "Python"
```python title="time_complexity.py"
[class]{}-[func]{factorial_recur}
```
=== "C++"
```cpp title="time_complexity.cpp"
[class]{}-[func]{factorialRecur}
```
=== "Java"
```java title="time_complexity.java"
[class]{time_complexity}-[func]{factorialRecur}
```
=== "C#"
```csharp title="time_complexity.cs"
[class]{time_complexity}-[func]{FactorialRecur}
```
=== "Go"
```go title="time_complexity.go"
[class]{}-[func]{factorialRecur}
```
=== "Swift"
```swift title="time_complexity.swift"
[class]{}-[func]{factorialRecur}
```
=== "JS"
```javascript title="time_complexity.js"
[class]{}-[func]{factorialRecur}
```
=== "TS"
```typescript title="time_complexity.ts"
[class]{}-[func]{factorialRecur}
```
=== "Dart"
```dart title="time_complexity.dart"
[class]{}-[func]{factorialRecur}
```
=== "Rust"
```rust title="time_complexity.rs"
[class]{}-[func]{factorial_recur}
```
=== "C"
```c title="time_complexity.c"
[class]{}-[func]{factorialRecur}
```
=== "Zig"
```zig title="time_complexity.zig"
[class]{}-[func]{factorialRecur}
```src
[file]{time_complexity}-[class]{}-[func]{factorial_recur}
```
![阶乘阶的时间复杂度](time_complexity.assets/time_complexity_factorial.png)
@ -1774,119 +1026,8 @@ $$
“最差时间复杂度”对应函数渐近上界,使用大 $O$ 记号表示。相应地,“最佳时间复杂度”对应函数渐近下界,用 $\Omega$ 记号表示:
=== "Python"
```python title="worst_best_time_complexity.py"
[class]{}-[func]{random_numbers}
[class]{}-[func]{find_one}
```
=== "C++"
```cpp title="worst_best_time_complexity.cpp"
[class]{}-[func]{randomNumbers}
[class]{}-[func]{findOne}
```
=== "Java"
```java title="worst_best_time_complexity.java"
[class]{worst_best_time_complexity}-[func]{randomNumbers}
[class]{worst_best_time_complexity}-[func]{findOne}
```
=== "C#"
```csharp title="worst_best_time_complexity.cs"
[class]{worst_best_time_complexity}-[func]{RandomNumbers}
[class]{worst_best_time_complexity}-[func]{FindOne}
```
=== "Go"
```go title="worst_best_time_complexity.go"
[class]{}-[func]{randomNumbers}
[class]{}-[func]{findOne}
```
=== "Swift"
```swift title="worst_best_time_complexity.swift"
[class]{}-[func]{randomNumbers}
[class]{}-[func]{findOne}
```
=== "JS"
```javascript title="worst_best_time_complexity.js"
[class]{}-[func]{randomNumbers}
[class]{}-[func]{findOne}
```
=== "TS"
```typescript title="worst_best_time_complexity.ts"
[class]{}-[func]{randomNumbers}
[class]{}-[func]{findOne}
```
=== "Dart"
```dart title="worst_best_time_complexity.dart"
[class]{}-[func]{randomNumbers}
[class]{}-[func]{findOne}
```
=== "Rust"
```rust title="worst_best_time_complexity.rs"
[class]{}-[func]{random_numbers}
[class]{}-[func]{find_one}
```
=== "C"
```c title="worst_best_time_complexity.c"
[class]{}-[func]{randomNumbers}
[class]{}-[func]{findOne}
```
=== "Zig"
```zig title="worst_best_time_complexity.zig"
// 生成一个数组,元素为 { 1, 2, ..., n },顺序被打乱
pub fn randomNumbers(comptime n: usize) [n]i32 {
var nums: [n]i32 = undefined;
// 生成数组 nums = { 1, 2, 3, ..., n }
for (nums) |*num, i| {
num.* = @intCast(i32, i) + 1;
}
// 随机打乱数组元素
const rand = std.crypto.random;
rand.shuffle(i32, &nums);
return nums;
}
// 查找数组 nums 中数字 1 所在索引
pub fn findOne(nums: []i32) i32 {
for (nums) |num, i| {
// 当元素 1 在数组头部时,达到最佳时间复杂度 O(1)
// 当元素 1 在数组尾部时,达到最差时间复杂度 O(n)
if (num == 1) return @intCast(i32, i);
}
return -1;
}
```src
[file]{worst_best_time_complexity}-[class]{}-[func]{find_one}
```
值得说明的是,我们在实际中很少使用最佳时间复杂度,因为通常只有在很小概率下才能达到,可能会带来一定的误导性。**而最差时间复杂度更为实用,因为它给出了一个效率安全值**,让我们可以放心地使用算法。

View file

@ -40,98 +40,6 @@
在实现代码中,我们声明一个递归函数 `dfs()` 来求解问题 $f(i, j)$ 。
=== "Python"
```python title="binary_search_recur.py"
[class]{}-[func]{dfs}
[class]{}-[func]{binary_search}
```
=== "C++"
```cpp title="binary_search_recur.cpp"
[class]{}-[func]{dfs}
[class]{}-[func]{binarySearch}
```
=== "Java"
```java title="binary_search_recur.java"
[class]{binary_search_recur}-[func]{dfs}
[class]{binary_search_recur}-[func]{binarySearch}
```
=== "C#"
```csharp title="binary_search_recur.cs"
[class]{binary_search_recur}-[func]{DFS}
[class]{binary_search_recur}-[func]{BinarySearch}
```
=== "Go"
```go title="binary_search_recur.go"
[class]{}-[func]{dfs}
[class]{}-[func]{binarySearch}
```
=== "Swift"
```swift title="binary_search_recur.swift"
[class]{}-[func]{dfs}
[class]{}-[func]{binarySearch}
```
=== "JS"
```javascript title="binary_search_recur.js"
[class]{}-[func]{dfs}
[class]{}-[func]{binarySearch}
```
=== "TS"
```typescript title="binary_search_recur.ts"
[class]{}-[func]{dfs}
[class]{}-[func]{binarySearch}
```
=== "Dart"
```dart title="binary_search_recur.dart"
[class]{}-[func]{dfs}
[class]{}-[func]{binarySearch}
```
=== "Rust"
```rust title="binary_search_recur.rs"
[class]{}-[func]{dfs}
[class]{}-[func]{binary_search}
```
=== "C"
```c title="binary_search_recur.c"
[class]{}-[func]{dfs}
[class]{}-[func]{binarySearch}
```
=== "Zig"
```zig title="binary_search_recur.zig"
[class]{}-[func]{dfs}
[class]{}-[func]{binarySearch}
```src
[file]{binary_search_recur}-[class]{}-[func]{binary_search}
```

View file

@ -57,100 +57,8 @@
为了提升查询 $m$ 的效率,我们借助一个哈希表 `hmap` 来存储数组 `inorder` 中元素到索引的映射。
=== "Python"
```python title="build_tree.py"
[class]{}-[func]{dfs}
[class]{}-[func]{build_tree}
```
=== "C++"
```cpp title="build_tree.cpp"
[class]{}-[func]{dfs}
[class]{}-[func]{buildTree}
```
=== "Java"
```java title="build_tree.java"
[class]{build_tree}-[func]{dfs}
[class]{build_tree}-[func]{buildTree}
```
=== "C#"
```csharp title="build_tree.cs"
[class]{build_tree}-[func]{DFS}
[class]{build_tree}-[func]{BuildTree}
```
=== "Go"
```go title="build_tree.go"
[class]{}-[func]{dfsBuildTree}
[class]{}-[func]{buildTree}
```
=== "Swift"
```swift title="build_tree.swift"
[class]{}-[func]{dfs}
[class]{}-[func]{buildTree}
```
=== "JS"
```javascript title="build_tree.js"
[class]{}-[func]{dfs}
[class]{}-[func]{buildTree}
```
=== "TS"
```typescript title="build_tree.ts"
[class]{}-[func]{dfs}
[class]{}-[func]{buildTree}
```
=== "Dart"
```dart title="build_tree.dart"
[class]{}-[func]{dfs}
[class]{}-[func]{buildTree}
```
=== "Rust"
```rust title="build_tree.rs"
[class]{}-[func]{dfs}
[class]{}-[func]{build_tree}
```
=== "C"
```c title="build_tree.c"
[class]{}-[func]{dfs}
[class]{}-[func]{buildTree}
```
=== "Zig"
```zig title="build_tree.zig"
[class]{}-[func]{dfs}
[class]{}-[func]{buildTree}
```src
[file]{build_tree}-[class]{}-[func]{build_tree}
```
下图展示了构建二叉树的递归过程,各个节点是在向下“递”的过程中建立的,而各条边(即引用)是在向上“归”的过程中建立的。

View file

@ -82,124 +82,8 @@
在代码中,我们声明一个递归函数 `dfs(i, src, buf, tar)` ,它的作用是将柱 `src` 顶部的 $i$ 个圆盘借助缓冲柱 `buf` 移动至目标柱 `tar`
=== "Python"
```python title="hanota.py"
[class]{}-[func]{move}
[class]{}-[func]{dfs}
[class]{}-[func]{solve_hanota}
```
=== "C++"
```cpp title="hanota.cpp"
[class]{}-[func]{move}
[class]{}-[func]{dfs}
[class]{}-[func]{solveHanota}
```
=== "Java"
```java title="hanota.java"
[class]{hanota}-[func]{move}
[class]{hanota}-[func]{dfs}
[class]{hanota}-[func]{solveHanota}
```
=== "C#"
```csharp title="hanota.cs"
[class]{hanota}-[func]{Move}
[class]{hanota}-[func]{DFS}
[class]{hanota}-[func]{SolveHanota}
```
=== "Go"
```go title="hanota.go"
[class]{}-[func]{move}
[class]{}-[func]{dfsHanota}
[class]{}-[func]{solveHanota}
```
=== "Swift"
```swift title="hanota.swift"
[class]{}-[func]{move}
[class]{}-[func]{dfs}
[class]{}-[func]{solveHanota}
```
=== "JS"
```javascript title="hanota.js"
[class]{}-[func]{move}
[class]{}-[func]{dfs}
[class]{}-[func]{solveHanota}
```
=== "TS"
```typescript title="hanota.ts"
[class]{}-[func]{move}
[class]{}-[func]{dfs}
[class]{}-[func]{solveHanota}
```
=== "Dart"
```dart title="hanota.dart"
[class]{}-[func]{move}
[class]{}-[func]{dfs}
[class]{}-[func]{solveHanota}
```
=== "Rust"
```rust title="hanota.rs"
[class]{}-[func]{move_pan}
[class]{}-[func]{dfs}
[class]{}-[func]{solve_hanota}
```
=== "C"
```c title="hanota.c"
[class]{}-[func]{move}
[class]{}-[func]{dfs}
[class]{}-[func]{solveHanota}
```
=== "Zig"
```zig title="hanota.zig"
[class]{}-[func]{move}
[class]{}-[func]{dfs}
[class]{}-[func]{solveHanota}
```src
[file]{hanota}-[class]{}-[func]{solve_hanota}
```
如下图所示,汉诺塔问题形成一个高度为 $n$ 的递归树,每个节点代表一个子问题、对应一个开启的 `dfs()` 函数,**因此时间复杂度为 $O(2^n)$ ,空间复杂度为 $O(n)$** 。

View file

@ -34,76 +34,8 @@ $$
根据状态转移方程,以及初始状态 $dp[1] = cost[1]$ 和 $dp[2] = cost[2]$ ,我们就可以得到动态规划代码。
=== "Python"
```python title="min_cost_climbing_stairs_dp.py"
[class]{}-[func]{min_cost_climbing_stairs_dp}
```
=== "C++"
```cpp title="min_cost_climbing_stairs_dp.cpp"
[class]{}-[func]{minCostClimbingStairsDP}
```
=== "Java"
```java title="min_cost_climbing_stairs_dp.java"
[class]{min_cost_climbing_stairs_dp}-[func]{minCostClimbingStairsDP}
```
=== "C#"
```csharp title="min_cost_climbing_stairs_dp.cs"
[class]{min_cost_climbing_stairs_dp}-[func]{MinCostClimbingStairsDP}
```
=== "Go"
```go title="min_cost_climbing_stairs_dp.go"
[class]{}-[func]{minCostClimbingStairsDP}
```
=== "Swift"
```swift title="min_cost_climbing_stairs_dp.swift"
[class]{}-[func]{minCostClimbingStairsDP}
```
=== "JS"
```javascript title="min_cost_climbing_stairs_dp.js"
[class]{}-[func]{minCostClimbingStairsDP}
```
=== "TS"
```typescript title="min_cost_climbing_stairs_dp.ts"
[class]{}-[func]{minCostClimbingStairsDP}
```
=== "Dart"
```dart title="min_cost_climbing_stairs_dp.dart"
[class]{}-[func]{minCostClimbingStairsDP}
```
=== "Rust"
```rust title="min_cost_climbing_stairs_dp.rs"
[class]{}-[func]{min_cost_climbing_stairs_dp}
```
=== "C"
```c title="min_cost_climbing_stairs_dp.c"
[class]{}-[func]{minCostClimbingStairsDP}
```
=== "Zig"
```zig title="min_cost_climbing_stairs_dp.zig"
[class]{}-[func]{minCostClimbingStairsDP}
```src
[file]{min_cost_climbing_stairs_dp}-[class]{}-[func]{min_cost_climbing_stairs_dp}
```
下图展示了以上代码的动态规划过程。
@ -112,76 +44,8 @@ $$
本题也可以进行空间优化,将一维压缩至零维,使得空间复杂度从 $O(n)$ 降低至 $O(1)$ 。
=== "Python"
```python title="min_cost_climbing_stairs_dp.py"
[class]{}-[func]{min_cost_climbing_stairs_dp_comp}
```
=== "C++"
```cpp title="min_cost_climbing_stairs_dp.cpp"
[class]{}-[func]{minCostClimbingStairsDPComp}
```
=== "Java"
```java title="min_cost_climbing_stairs_dp.java"
[class]{min_cost_climbing_stairs_dp}-[func]{minCostClimbingStairsDPComp}
```
=== "C#"
```csharp title="min_cost_climbing_stairs_dp.cs"
[class]{min_cost_climbing_stairs_dp}-[func]{MinCostClimbingStairsDPComp}
```
=== "Go"
```go title="min_cost_climbing_stairs_dp.go"
[class]{}-[func]{minCostClimbingStairsDPComp}
```
=== "Swift"
```swift title="min_cost_climbing_stairs_dp.swift"
[class]{}-[func]{minCostClimbingStairsDPComp}
```
=== "JS"
```javascript title="min_cost_climbing_stairs_dp.js"
[class]{}-[func]{minCostClimbingStairsDPComp}
```
=== "TS"
```typescript title="min_cost_climbing_stairs_dp.ts"
[class]{}-[func]{minCostClimbingStairsDPComp}
```
=== "Dart"
```dart title="min_cost_climbing_stairs_dp.dart"
[class]{}-[func]{minCostClimbingStairsDPComp}
```
=== "Rust"
```rust title="min_cost_climbing_stairs_dp.rs"
[class]{}-[func]{min_cost_climbing_stairs_dp_comp}
```
=== "C"
```c title="min_cost_climbing_stairs_dp.c"
[class]{}-[func]{minCostClimbingStairsDPComp}
```
=== "Zig"
```zig title="min_cost_climbing_stairs_dp.zig"
[class]{}-[func]{minCostClimbingStairsDPComp}
```src
[file]{min_cost_climbing_stairs_dp}-[class]{}-[func]{min_cost_climbing_stairs_dp_comp}
```
## 无后效性
@ -222,76 +86,8 @@ $$
最终,返回 $dp[n, 1] + dp[n, 2]$ 即可,两者之和代表爬到第 $n$ 阶的方案总数。
=== "Python"
```python title="climbing_stairs_constraint_dp.py"
[class]{}-[func]{climbing_stairs_constraint_dp}
```
=== "C++"
```cpp title="climbing_stairs_constraint_dp.cpp"
[class]{}-[func]{climbingStairsConstraintDP}
```
=== "Java"
```java title="climbing_stairs_constraint_dp.java"
[class]{climbing_stairs_constraint_dp}-[func]{climbingStairsConstraintDP}
```
=== "C#"
```csharp title="climbing_stairs_constraint_dp.cs"
[class]{climbing_stairs_constraint_dp}-[func]{ClimbingStairsConstraintDP}
```
=== "Go"
```go title="climbing_stairs_constraint_dp.go"
[class]{}-[func]{climbingStairsConstraintDP}
```
=== "Swift"
```swift title="climbing_stairs_constraint_dp.swift"
[class]{}-[func]{climbingStairsConstraintDP}
```
=== "JS"
```javascript title="climbing_stairs_constraint_dp.js"
[class]{}-[func]{climbingStairsConstraintDP}
```
=== "TS"
```typescript title="climbing_stairs_constraint_dp.ts"
[class]{}-[func]{climbingStairsConstraintDP}
```
=== "Dart"
```dart title="climbing_stairs_constraint_dp.dart"
[class]{}-[func]{climbingStairsConstraintDP}
```
=== "Rust"
```rust title="climbing_stairs_constraint_dp.rs"
[class]{}-[func]{climbing_stairs_constraint_dp}
```
=== "C"
```c title="climbing_stairs_constraint_dp.c"
[class]{}-[func]{climbingStairsConstraintDP}
```
=== "Zig"
```zig title="climbing_stairs_constraint_dp.zig"
[class]{}-[func]{climbingStairsConstraintDP}
```src
[file]{climbing_stairs_constraint_dp}-[class]{}-[func]{climbing_stairs_constraint_dp}
```
在上面的案例中,由于仅需多考虑前面一个状态,我们仍然可以通过扩展状态定义,使得问题重新满足无后效性。然而,某些问题具有非常严重的“有后效性”。

View file

@ -98,76 +98,8 @@ $$
- **终止条件**:当 $i = 0$ 且 $j = 0$ 时,返回代价 $grid[0, 0]$ 。
- **剪枝**:当 $i < 0$ 时或 $j < 0$ 时索引越界此时返回代价 $+\infty$ 代表不可行
=== "Python"
```python title="min_path_sum.py"
[class]{}-[func]{min_path_sum_dfs}
```
=== "C++"
```cpp title="min_path_sum.cpp"
[class]{}-[func]{minPathSumDFS}
```
=== "Java"
```java title="min_path_sum.java"
[class]{min_path_sum}-[func]{minPathSumDFS}
```
=== "C#"
```csharp title="min_path_sum.cs"
[class]{min_path_sum}-[func]{MinPathSumDFS}
```
=== "Go"
```go title="min_path_sum.go"
[class]{}-[func]{minPathSumDFS}
```
=== "Swift"
```swift title="min_path_sum.swift"
[class]{}-[func]{minPathSumDFS}
```
=== "JS"
```javascript title="min_path_sum.js"
[class]{}-[func]{minPathSumDFS}
```
=== "TS"
```typescript title="min_path_sum.ts"
[class]{}-[func]{minPathSumDFS}
```
=== "Dart"
```dart title="min_path_sum.dart"
[class]{}-[func]{minPathSumDFS}
```
=== "Rust"
```rust title="min_path_sum.rs"
[class]{}-[func]{min_path_sum_dfs}
```
=== "C"
```c title="min_path_sum.c"
[class]{}-[func]{minPathSumDFS}
```
=== "Zig"
```zig title="min_path_sum.zig"
[class]{}-[func]{minPathSumDFS}
```src
[file]{min_path_sum}-[class]{}-[func]{min_path_sum_dfs}
```
下图给出了以 $dp[2, 1]$ 为根节点的递归树,其中包含一些重叠子问题,其数量会随着网格 `grid` 的尺寸变大而急剧增多。
@ -182,76 +114,8 @@ $$
我们引入一个和网格 `grid` 相同尺寸的记忆列表 `mem` ,用于记录各个子问题的解,并将重叠子问题进行剪枝。
=== "Python"
```python title="min_path_sum.py"
[class]{}-[func]{min_path_sum_dfs_mem}
```
=== "C++"
```cpp title="min_path_sum.cpp"
[class]{}-[func]{minPathSumDFSMem}
```
=== "Java"
```java title="min_path_sum.java"
[class]{min_path_sum}-[func]{minPathSumDFSMem}
```
=== "C#"
```csharp title="min_path_sum.cs"
[class]{min_path_sum}-[func]{MinPathSumDFSMem}
```
=== "Go"
```go title="min_path_sum.go"
[class]{}-[func]{minPathSumDFSMem}
```
=== "Swift"
```swift title="min_path_sum.swift"
[class]{}-[func]{minPathSumDFSMem}
```
=== "JS"
```javascript title="min_path_sum.js"
[class]{}-[func]{minPathSumDFSMem}
```
=== "TS"
```typescript title="min_path_sum.ts"
[class]{}-[func]{minPathSumDFSMem}
```
=== "Dart"
```dart title="min_path_sum.dart"
[class]{}-[func]{minPathSumDFSMem}
```
=== "Rust"
```rust title="min_path_sum.rs"
[class]{}-[func]{min_path_sum_dfs_mem}
```
=== "C"
```c title="min_path_sum.c"
[class]{}-[func]{minPathSumDFSMem}
```
=== "Zig"
```zig title="min_path_sum.zig"
[class]{}-[func]{minPathSumDFSMem}
```src
[file]{min_path_sum}-[class]{}-[func]{min_path_sum_dfs_mem}
```
如下图所示,在引入记忆化后,所有子问题的解只需计算一次,因此时间复杂度取决于状态总数,即网格尺寸 $O(nm)$ 。
@ -262,76 +126,8 @@ $$
基于迭代实现动态规划解法。
=== "Python"
```python title="min_path_sum.py"
[class]{}-[func]{min_path_sum_dp}
```
=== "C++"
```cpp title="min_path_sum.cpp"
[class]{}-[func]{minPathSumDP}
```
=== "Java"
```java title="min_path_sum.java"
[class]{min_path_sum}-[func]{minPathSumDP}
```
=== "C#"
```csharp title="min_path_sum.cs"
[class]{min_path_sum}-[func]{MinPathSumDP}
```
=== "Go"
```go title="min_path_sum.go"
[class]{}-[func]{minPathSumDP}
```
=== "Swift"
```swift title="min_path_sum.swift"
[class]{}-[func]{minPathSumDP}
```
=== "JS"
```javascript title="min_path_sum.js"
[class]{}-[func]{minPathSumDP}
```
=== "TS"
```typescript title="min_path_sum.ts"
[class]{}-[func]{minPathSumDP}
```
=== "Dart"
```dart title="min_path_sum.dart"
[class]{}-[func]{minPathSumDP}
```
=== "Rust"
```rust title="min_path_sum.rs"
[class]{}-[func]{min_path_sum_dp}
```
=== "C"
```c title="min_path_sum.c"
[class]{}-[func]{minPathSumDP}
```
=== "Zig"
```zig title="min_path_sum.zig"
[class]{}-[func]{minPathSumDP}
```src
[file]{min_path_sum}-[class]{}-[func]{min_path_sum_dp}
```
下图展示了最小路径和的状态转移过程,其遍历了整个网格,**因此时间复杂度为 $O(nm)$** 。
@ -380,74 +176,6 @@ $$
请注意,因为数组 `dp` 只能表示一行的状态,所以我们无法提前初始化首列状态,而是在遍历每行中更新它。
=== "Python"
```python title="min_path_sum.py"
[class]{}-[func]{min_path_sum_dp_comp}
```
=== "C++"
```cpp title="min_path_sum.cpp"
[class]{}-[func]{minPathSumDPComp}
```
=== "Java"
```java title="min_path_sum.java"
[class]{min_path_sum}-[func]{minPathSumDPComp}
```
=== "C#"
```csharp title="min_path_sum.cs"
[class]{min_path_sum}-[func]{MinPathSumDPComp}
```
=== "Go"
```go title="min_path_sum.go"
[class]{}-[func]{minPathSumDPComp}
```
=== "Swift"
```swift title="min_path_sum.swift"
[class]{}-[func]{minPathSumDPComp}
```
=== "JS"
```javascript title="min_path_sum.js"
[class]{}-[func]{minPathSumDPComp}
```
=== "TS"
```typescript title="min_path_sum.ts"
[class]{}-[func]{minPathSumDPComp}
```
=== "Dart"
```dart title="min_path_sum.dart"
[class]{}-[func]{minPathSumDPComp}
```
=== "Rust"
```rust title="min_path_sum.rs"
[class]{}-[func]{min_path_sum_dp_comp}
```
=== "C"
```c title="min_path_sum.c"
[class]{}-[func]{minPathSumDPComp}
```
=== "Zig"
```zig title="min_path_sum.zig"
[class]{}-[func]{minPathSumDPComp}
```src
[file]{min_path_sum}-[class]{}-[func]{min_path_sum_dp_comp}
```

View file

@ -67,76 +67,8 @@ $$
### 代码实现
=== "Python"
```python title="edit_distance.py"
[class]{}-[func]{edit_distance_dp}
```
=== "C++"
```cpp title="edit_distance.cpp"
[class]{}-[func]{editDistanceDP}
```
=== "Java"
```java title="edit_distance.java"
[class]{edit_distance}-[func]{editDistanceDP}
```
=== "C#"
```csharp title="edit_distance.cs"
[class]{edit_distance}-[func]{EditDistanceDP}
```
=== "Go"
```go title="edit_distance.go"
[class]{}-[func]{editDistanceDP}
```
=== "Swift"
```swift title="edit_distance.swift"
[class]{}-[func]{editDistanceDP}
```
=== "JS"
```javascript title="edit_distance.js"
[class]{}-[func]{editDistanceDP}
```
=== "TS"
```typescript title="edit_distance.ts"
[class]{}-[func]{editDistanceDP}
```
=== "Dart"
```dart title="edit_distance.dart"
[class]{}-[func]{editDistanceDP}
```
=== "Rust"
```rust title="edit_distance.rs"
[class]{}-[func]{edit_distance_dp}
```
=== "C"
```c title="edit_distance.c"
[class]{}-[func]{editDistanceDP}
```
=== "Zig"
```zig title="edit_distance.zig"
[class]{}-[func]{editDistanceDP}
```src
[file]{edit_distance}-[class]{}-[func]{edit_distance_dp}
```
如下图所示,编辑距离问题的状态转移过程与背包问题非常类似,都可以看作是填写一个二维网格的过程。
@ -192,74 +124,6 @@ $$
为此,我们可以使用一个变量 `leftup` 来暂存左上方的解 $dp[i-1, j-1]$ ,从而只需考虑左方和上方的解。此时的情况与完全背包问题相同,可使用正序遍历。
=== "Python"
```python title="edit_distance.py"
[class]{}-[func]{edit_distance_dp_comp}
```
=== "C++"
```cpp title="edit_distance.cpp"
[class]{}-[func]{editDistanceDPComp}
```
=== "Java"
```java title="edit_distance.java"
[class]{edit_distance}-[func]{editDistanceDPComp}
```
=== "C#"
```csharp title="edit_distance.cs"
[class]{edit_distance}-[func]{EditDistanceDPComp}
```
=== "Go"
```go title="edit_distance.go"
[class]{}-[func]{editDistanceDPComp}
```
=== "Swift"
```swift title="edit_distance.swift"
[class]{}-[func]{editDistanceDPComp}
```
=== "JS"
```javascript title="edit_distance.js"
[class]{}-[func]{editDistanceDPComp}
```
=== "TS"
```typescript title="edit_distance.ts"
[class]{}-[func]{editDistanceDPComp}
```
=== "Dart"
```dart title="edit_distance.dart"
[class]{}-[func]{editDistanceDPComp}
```
=== "Rust"
```rust title="edit_distance.rs"
[class]{}-[func]{edit_distance_dp_comp}
```
=== "C"
```c title="edit_distance.c"
[class]{}-[func]{editDistanceDPComp}
```
=== "Zig"
```zig title="edit_distance.zig"
[class]{}-[func]{editDistanceDPComp}
```src
[file]{edit_distance}-[class]{}-[func]{edit_distance_dp_comp}
```

View file

@ -14,100 +14,8 @@
本题的目标是求解方案数量,**我们可以考虑通过回溯来穷举所有可能性**。具体来说,将爬楼梯想象为一个多轮选择的过程:从地面出发,每轮选择上 $1$ 阶或 $2$ 阶,每当到达楼梯顶部时就将方案数量加 $1$ ,当越过楼梯顶部时就将其剪枝。
=== "Python"
```python title="climbing_stairs_backtrack.py"
[class]{}-[func]{backtrack}
[class]{}-[func]{climbing_stairs_backtrack}
```
=== "C++"
```cpp title="climbing_stairs_backtrack.cpp"
[class]{}-[func]{backtrack}
[class]{}-[func]{climbingStairsBacktrack}
```
=== "Java"
```java title="climbing_stairs_backtrack.java"
[class]{climbing_stairs_backtrack}-[func]{backtrack}
[class]{climbing_stairs_backtrack}-[func]{climbingStairsBacktrack}
```
=== "C#"
```csharp title="climbing_stairs_backtrack.cs"
[class]{climbing_stairs_backtrack}-[func]{Backtrack}
[class]{climbing_stairs_backtrack}-[func]{ClimbingStairsBacktrack}
```
=== "Go"
```go title="climbing_stairs_backtrack.go"
[class]{}-[func]{backtrack}
[class]{}-[func]{climbingStairsBacktrack}
```
=== "Swift"
```swift title="climbing_stairs_backtrack.swift"
[class]{}-[func]{backtrack}
[class]{}-[func]{climbingStairsBacktrack}
```
=== "JS"
```javascript title="climbing_stairs_backtrack.js"
[class]{}-[func]{backtrack}
[class]{}-[func]{climbingStairsBacktrack}
```
=== "TS"
```typescript title="climbing_stairs_backtrack.ts"
[class]{}-[func]{backtrack}
[class]{}-[func]{climbingStairsBacktrack}
```
=== "Dart"
```dart title="climbing_stairs_backtrack.dart"
[class]{}-[func]{backtrack}
[class]{}-[func]{climbingStairsBacktrack}
```
=== "Rust"
```rust title="climbing_stairs_backtrack.rs"
[class]{}-[func]{backtrack}
[class]{}-[func]{climbing_stairs_backtrack}
```
=== "C"
```c title="climbing_stairs_backtrack.c"
[class]{}-[func]{backtrack}
[class]{}-[func]{climbingStairsBacktrack}
```
=== "Zig"
```zig title="climbing_stairs_backtrack.zig"
[class]{}-[func]{backtrack}
[class]{}-[func]{climbingStairsBacktrack}
```src
[file]{climbing_stairs_backtrack}-[class]{}-[func]{climbing_stairs_backtrack}
```
## 方法一:暴力搜索
@ -136,100 +44,8 @@ $$
观察以下代码,它和标准回溯代码都属于深度优先搜索,但更加简洁。
=== "Python"
```python title="climbing_stairs_dfs.py"
[class]{}-[func]{dfs}
[class]{}-[func]{climbing_stairs_dfs}
```
=== "C++"
```cpp title="climbing_stairs_dfs.cpp"
[class]{}-[func]{dfs}
[class]{}-[func]{climbingStairsDFS}
```
=== "Java"
```java title="climbing_stairs_dfs.java"
[class]{climbing_stairs_dfs}-[func]{dfs}
[class]{climbing_stairs_dfs}-[func]{climbingStairsDFS}
```
=== "C#"
```csharp title="climbing_stairs_dfs.cs"
[class]{climbing_stairs_dfs}-[func]{DFS}
[class]{climbing_stairs_dfs}-[func]{ClimbingStairsDFS}
```
=== "Go"
```go title="climbing_stairs_dfs.go"
[class]{}-[func]{dfs}
[class]{}-[func]{climbingStairsDFS}
```
=== "Swift"
```swift title="climbing_stairs_dfs.swift"
[class]{}-[func]{dfs}
[class]{}-[func]{climbingStairsDFS}
```
=== "JS"
```javascript title="climbing_stairs_dfs.js"
[class]{}-[func]{dfs}
[class]{}-[func]{climbingStairsDFS}
```
=== "TS"
```typescript title="climbing_stairs_dfs.ts"
[class]{}-[func]{dfs}
[class]{}-[func]{climbingStairsDFS}
```
=== "Dart"
```dart title="climbing_stairs_dfs.dart"
[class]{}-[func]{dfs}
[class]{}-[func]{climbingStairsDFS}
```
=== "Rust"
```rust title="climbing_stairs_dfs.rs"
[class]{}-[func]{dfs}
[class]{}-[func]{climbing_stairs_dfs}
```
=== "C"
```c title="climbing_stairs_dfs.c"
[class]{}-[func]{dfs}
[class]{}-[func]{climbingStairsDFS}
```
=== "Zig"
```zig title="climbing_stairs_dfs.zig"
[class]{}-[func]{dfs}
[class]{}-[func]{climbingStairsDFS}
```src
[file]{climbing_stairs_dfs}-[class]{}-[func]{climbing_stairs_dfs}
```
下图展示了暴力搜索形成的递归树。对于问题 $dp[n]$ ,其递归树的深度为 $n$ ,时间复杂度为 $O(2^n)$ 。指数阶属于爆炸式增长,如果我们输入一个比较大的 $n$ ,则会陷入漫长的等待之中。
@ -247,100 +63,8 @@ $$
1. 当首次计算 $dp[i]$ 时,我们将其记录至 `mem[i]` ,以便之后使用。
2. 当再次需要计算 $dp[i]$ 时,我们便可直接从 `mem[i]` 中获取结果,从而避免重复计算该子问题。
=== "Python"
```python title="climbing_stairs_dfs_mem.py"
[class]{}-[func]{dfs}
[class]{}-[func]{climbing_stairs_dfs_mem}
```
=== "C++"
```cpp title="climbing_stairs_dfs_mem.cpp"
[class]{}-[func]{dfs}
[class]{}-[func]{climbingStairsDFSMem}
```
=== "Java"
```java title="climbing_stairs_dfs_mem.java"
[class]{climbing_stairs_dfs_mem}-[func]{dfs}
[class]{climbing_stairs_dfs_mem}-[func]{climbingStairsDFSMem}
```
=== "C#"
```csharp title="climbing_stairs_dfs_mem.cs"
[class]{climbing_stairs_dfs_mem}-[func]{DFS}
[class]{climbing_stairs_dfs_mem}-[func]{ClimbingStairsDFSMem}
```
=== "Go"
```go title="climbing_stairs_dfs_mem.go"
[class]{}-[func]{dfsMem}
[class]{}-[func]{climbingStairsDFSMem}
```
=== "Swift"
```swift title="climbing_stairs_dfs_mem.swift"
[class]{}-[func]{dfs}
[class]{}-[func]{climbingStairsDFSMem}
```
=== "JS"
```javascript title="climbing_stairs_dfs_mem.js"
[class]{}-[func]{dfs}
[class]{}-[func]{climbingStairsDFSMem}
```
=== "TS"
```typescript title="climbing_stairs_dfs_mem.ts"
[class]{}-[func]{dfs}
[class]{}-[func]{climbingStairsDFSMem}
```
=== "Dart"
```dart title="climbing_stairs_dfs_mem.dart"
[class]{}-[func]{dfs}
[class]{}-[func]{climbingStairsDFSMem}
```
=== "Rust"
```rust title="climbing_stairs_dfs_mem.rs"
[class]{}-[func]{dfs}
[class]{}-[func]{climbing_stairs_dfs_mem}
```
=== "C"
```c title="climbing_stairs_dfs_mem.c"
[class]{}-[func]{dfs}
[class]{}-[func]{climbingStairsDFSMem}
```
=== "Zig"
```zig title="climbing_stairs_dfs_mem.zig"
[class]{}-[func]{dfs}
[class]{}-[func]{climbingStairsDFSMem}
```src
[file]{climbing_stairs_dfs_mem}-[class]{}-[func]{climbing_stairs_dfs_mem}
```
观察下图,**经过记忆化处理后,所有重叠子问题都只需被计算一次,时间复杂度被优化至 $O(n)$** ,这是一个巨大的飞跃。
@ -355,76 +79,8 @@ $$
由于动态规划不包含回溯过程,因此只需使用循环迭代实现,无须使用递归。在以下代码中,我们初始化一个数组 `dp` 来存储子问题的解,它起到了记忆化搜索中数组 `mem` 相同的记录作用。
=== "Python"
```python title="climbing_stairs_dp.py"
[class]{}-[func]{climbing_stairs_dp}
```
=== "C++"
```cpp title="climbing_stairs_dp.cpp"
[class]{}-[func]{climbingStairsDP}
```
=== "Java"
```java title="climbing_stairs_dp.java"
[class]{climbing_stairs_dp}-[func]{climbingStairsDP}
```
=== "C#"
```csharp title="climbing_stairs_dp.cs"
[class]{climbing_stairs_dp}-[func]{ClimbingStairsDP}
```
=== "Go"
```go title="climbing_stairs_dp.go"
[class]{}-[func]{climbingStairsDP}
```
=== "Swift"
```swift title="climbing_stairs_dp.swift"
[class]{}-[func]{climbingStairsDP}
```
=== "JS"
```javascript title="climbing_stairs_dp.js"
[class]{}-[func]{climbingStairsDP}
```
=== "TS"
```typescript title="climbing_stairs_dp.ts"
[class]{}-[func]{climbingStairsDP}
```
=== "Dart"
```dart title="climbing_stairs_dp.dart"
[class]{}-[func]{climbingStairsDP}
```
=== "Rust"
```rust title="climbing_stairs_dp.rs"
[class]{}-[func]{climbing_stairs_dp}
```
=== "C"
```c title="climbing_stairs_dp.c"
[class]{}-[func]{climbingStairsDP}
```
=== "Zig"
```zig title="climbing_stairs_dp.zig"
[class]{}-[func]{climbingStairsDP}
```src
[file]{climbing_stairs_dp}-[class]{}-[func]{climbing_stairs_dp}
```
下图模拟了以上代码的执行过程。
@ -443,76 +99,8 @@ $$
细心的你可能发现,**由于 $dp[i]$ 只与 $dp[i-1]$ 和 $dp[i-2]$ 有关,因此我们无须使用一个数组 `dp` 来存储所有子问题的解**,而只需两个变量滚动前进即可。
=== "Python"
```python title="climbing_stairs_dp.py"
[class]{}-[func]{climbing_stairs_dp_comp}
```
=== "C++"
```cpp title="climbing_stairs_dp.cpp"
[class]{}-[func]{climbingStairsDPComp}
```
=== "Java"
```java title="climbing_stairs_dp.java"
[class]{climbing_stairs_dp}-[func]{climbingStairsDPComp}
```
=== "C#"
```csharp title="climbing_stairs_dp.cs"
[class]{climbing_stairs_dp}-[func]{ClimbingStairsDPComp}
```
=== "Go"
```go title="climbing_stairs_dp.go"
[class]{}-[func]{climbingStairsDPComp}
```
=== "Swift"
```swift title="climbing_stairs_dp.swift"
[class]{}-[func]{climbingStairsDPComp}
```
=== "JS"
```javascript title="climbing_stairs_dp.js"
[class]{}-[func]{climbingStairsDPComp}
```
=== "TS"
```typescript title="climbing_stairs_dp.ts"
[class]{}-[func]{climbingStairsDPComp}
```
=== "Dart"
```dart title="climbing_stairs_dp.dart"
[class]{}-[func]{climbingStairsDPComp}
```
=== "Rust"
```rust title="climbing_stairs_dp.rs"
[class]{}-[func]{climbing_stairs_dp_comp}
```
=== "C"
```c title="climbing_stairs_dp.c"
[class]{}-[func]{climbingStairsDPComp}
```
=== "Zig"
```zig title="climbing_stairs_dp.zig"
[class]{}-[func]{climbingStairsDPComp}
```src
[file]{climbing_stairs_dp}-[class]{}-[func]{climbing_stairs_dp_comp}
```
观察以上代码,由于省去了数组 `dp` 占用的空间,因此空间复杂度从 $O(n)$ 降低至 $O(1)$ 。

View file

@ -56,76 +56,8 @@ $$
- **终止条件**:当物品编号越界 $i = 0$ 或背包剩余容量为 $0$ 时,终止递归并返回价值 $0$ 。
- **剪枝**:若当前物品重量超出背包剩余容量,则只能不放入背包。
=== "Python"
```python title="knapsack.py"
[class]{}-[func]{knapsack_dfs}
```
=== "C++"
```cpp title="knapsack.cpp"
[class]{}-[func]{knapsackDFS}
```
=== "Java"
```java title="knapsack.java"
[class]{knapsack}-[func]{knapsackDFS}
```
=== "C#"
```csharp title="knapsack.cs"
[class]{knapsack}-[func]{KnapsackDFS}
```
=== "Go"
```go title="knapsack.go"
[class]{}-[func]{knapsackDFS}
```
=== "Swift"
```swift title="knapsack.swift"
[class]{}-[func]{knapsackDFS}
```
=== "JS"
```javascript title="knapsack.js"
[class]{}-[func]{knapsackDFS}
```
=== "TS"
```typescript title="knapsack.ts"
[class]{}-[func]{knapsackDFS}
```
=== "Dart"
```dart title="knapsack.dart"
[class]{}-[func]{knapsackDFS}
```
=== "Rust"
```rust title="knapsack.rs"
[class]{}-[func]{knapsack_dfs}
```
=== "C"
```c title="knapsack.c"
[class]{}-[func]{knapsackDFS}
```
=== "Zig"
```zig title="knapsack.zig"
[class]{}-[func]{knapsackDFS}
```src
[file]{knapsack}-[class]{}-[func]{knapsack_dfs}
```
如下图所示,由于每个物品都会产生不选和选两条搜索分支,因此时间复杂度为 $O(2^n)$ 。
@ -140,76 +72,8 @@ $$
引入记忆化之后,**时间复杂度取决于子问题数量**,也就是 $O(n \times cap)$ 。
=== "Python"
```python title="knapsack.py"
[class]{}-[func]{knapsack_dfs_mem}
```
=== "C++"
```cpp title="knapsack.cpp"
[class]{}-[func]{knapsackDFSMem}
```
=== "Java"
```java title="knapsack.java"
[class]{knapsack}-[func]{knapsackDFSMem}
```
=== "C#"
```csharp title="knapsack.cs"
[class]{knapsack}-[func]{KnapsackDFSMem}
```
=== "Go"
```go title="knapsack.go"
[class]{}-[func]{knapsackDFSMem}
```
=== "Swift"
```swift title="knapsack.swift"
[class]{}-[func]{knapsackDFSMem}
```
=== "JS"
```javascript title="knapsack.js"
[class]{}-[func]{knapsackDFSMem}
```
=== "TS"
```typescript title="knapsack.ts"
[class]{}-[func]{knapsackDFSMem}
```
=== "Dart"
```dart title="knapsack.dart"
[class]{}-[func]{knapsackDFSMem}
```
=== "Rust"
```rust title="knapsack.rs"
[class]{}-[func]{knapsack_dfs_mem}
```
=== "C"
```c title="knapsack.c"
[class]{}-[func]{knapsackDFSMem}
```
=== "Zig"
```zig title="knapsack.zig"
[class]{}-[func]{knapsackDFSMem}
```src
[file]{knapsack}-[class]{}-[func]{knapsack_dfs_mem}
```
下图展示了在记忆化递归中被剪掉的搜索分支。
@ -220,76 +84,8 @@ $$
动态规划实质上就是在状态转移中填充 $dp$ 表的过程,代码如下所示。
=== "Python"
```python title="knapsack.py"
[class]{}-[func]{knapsack_dp}
```
=== "C++"
```cpp title="knapsack.cpp"
[class]{}-[func]{knapsackDP}
```
=== "Java"
```java title="knapsack.java"
[class]{knapsack}-[func]{knapsackDP}
```
=== "C#"
```csharp title="knapsack.cs"
[class]{knapsack}-[func]{KnapsackDP}
```
=== "Go"
```go title="knapsack.go"
[class]{}-[func]{knapsackDP}
```
=== "Swift"
```swift title="knapsack.swift"
[class]{}-[func]{knapsackDP}
```
=== "JS"
```javascript title="knapsack.js"
[class]{}-[func]{knapsackDP}
```
=== "TS"
```typescript title="knapsack.ts"
[class]{}-[func]{knapsackDP}
```
=== "Dart"
```dart title="knapsack.dart"
[class]{}-[func]{knapsackDP}
```
=== "Rust"
```rust title="knapsack.rs"
[class]{}-[func]{knapsack_dp}
```
=== "C"
```c title="knapsack.c"
[class]{}-[func]{knapsackDP}
```
=== "Zig"
```zig title="knapsack.zig"
[class]{}-[func]{knapsackDP}
```src
[file]{knapsack}-[class]{}-[func]{knapsack_dp}
```
如下图所示,时间复杂度和空间复杂度都由数组 `dp` 大小决定,即 $O(n \times cap)$ 。
@ -367,74 +163,6 @@ $$
在代码实现中,我们仅需将数组 `dp` 的第一维 $i$ 直接删除,并且把内循环更改为倒序遍历即可。
=== "Python"
```python title="knapsack.py"
[class]{}-[func]{knapsack_dp_comp}
```
=== "C++"
```cpp title="knapsack.cpp"
[class]{}-[func]{knapsackDPComp}
```
=== "Java"
```java title="knapsack.java"
[class]{knapsack}-[func]{knapsackDPComp}
```
=== "C#"
```csharp title="knapsack.cs"
[class]{knapsack}-[func]{KnapsackDPComp}
```
=== "Go"
```go title="knapsack.go"
[class]{}-[func]{knapsackDPComp}
```
=== "Swift"
```swift title="knapsack.swift"
[class]{}-[func]{knapsackDPComp}
```
=== "JS"
```javascript title="knapsack.js"
[class]{}-[func]{knapsackDPComp}
```
=== "TS"
```typescript title="knapsack.ts"
[class]{}-[func]{knapsackDPComp}
```
=== "Dart"
```dart title="knapsack.dart"
[class]{}-[func]{knapsackDPComp}
```
=== "Rust"
```rust title="knapsack.rs"
[class]{}-[func]{knapsack_dp_comp}
```
=== "C"
```c title="knapsack.c"
[class]{}-[func]{knapsackDPComp}
```
=== "Zig"
```zig title="knapsack.zig"
[class]{}-[func]{knapsackDPComp}
```src
[file]{knapsack}-[class]{}-[func]{knapsack_dp_comp}
```

View file

@ -32,76 +32,8 @@ $$
对比两道题目的代码,状态转移中有一处从 $i-1$ 变为 $i$ ,其余完全一致。
=== "Python"
```python title="unbounded_knapsack.py"
[class]{}-[func]{unbounded_knapsack_dp}
```
=== "C++"
```cpp title="unbounded_knapsack.cpp"
[class]{}-[func]{unboundedKnapsackDP}
```
=== "Java"
```java title="unbounded_knapsack.java"
[class]{unbounded_knapsack}-[func]{unboundedKnapsackDP}
```
=== "C#"
```csharp title="unbounded_knapsack.cs"
[class]{unbounded_knapsack}-[func]{UnboundedKnapsackDP}
```
=== "Go"
```go title="unbounded_knapsack.go"
[class]{}-[func]{unboundedKnapsackDP}
```
=== "Swift"
```swift title="unbounded_knapsack.swift"
[class]{}-[func]{unboundedKnapsackDP}
```
=== "JS"
```javascript title="unbounded_knapsack.js"
[class]{}-[func]{unboundedKnapsackDP}
```
=== "TS"
```typescript title="unbounded_knapsack.ts"
[class]{}-[func]{unboundedKnapsackDP}
```
=== "Dart"
```dart title="unbounded_knapsack.dart"
[class]{}-[func]{unboundedKnapsackDP}
```
=== "Rust"
```rust title="unbounded_knapsack.rs"
[class]{}-[func]{unbounded_knapsack_dp}
```
=== "C"
```c title="unbounded_knapsack.c"
[class]{}-[func]{unboundedKnapsackDP}
```
=== "Zig"
```zig title="unbounded_knapsack.zig"
[class]{}-[func]{unboundedKnapsackDP}
```src
[file]{unbounded_knapsack}-[class]{}-[func]{unbounded_knapsack_dp}
```
### 空间优化
@ -130,76 +62,8 @@ $$
代码实现比较简单,仅需将数组 `dp` 的第一维删除。
=== "Python"
```python title="unbounded_knapsack.py"
[class]{}-[func]{unbounded_knapsack_dp_comp}
```
=== "C++"
```cpp title="unbounded_knapsack.cpp"
[class]{}-[func]{unboundedKnapsackDPComp}
```
=== "Java"
```java title="unbounded_knapsack.java"
[class]{unbounded_knapsack}-[func]{unboundedKnapsackDPComp}
```
=== "C#"
```csharp title="unbounded_knapsack.cs"
[class]{unbounded_knapsack}-[func]{UnboundedKnapsackDPComp}
```
=== "Go"
```go title="unbounded_knapsack.go"
[class]{}-[func]{unboundedKnapsackDPComp}
```
=== "Swift"
```swift title="unbounded_knapsack.swift"
[class]{}-[func]{unboundedKnapsackDPComp}
```
=== "JS"
```javascript title="unbounded_knapsack.js"
[class]{}-[func]{unboundedKnapsackDPComp}
```
=== "TS"
```typescript title="unbounded_knapsack.ts"
[class]{}-[func]{unboundedKnapsackDPComp}
```
=== "Dart"
```dart title="unbounded_knapsack.dart"
[class]{}-[func]{unboundedKnapsackDPComp}
```
=== "Rust"
```rust title="unbounded_knapsack.rs"
[class]{}-[func]{unbounded_knapsack_dp_comp}
```
=== "C"
```c title="unbounded_knapsack.c"
[class]{}-[func]{unboundedKnapsackDPComp}
```
=== "Zig"
```zig title="unbounded_knapsack.zig"
[class]{}-[func]{unboundedKnapsackDPComp}
```src
[file]{unbounded_knapsack}-[class]{}-[func]{unbounded_knapsack_dp_comp}
```
## 零钱兑换问题
@ -251,76 +115,8 @@ $$
最后返回前,判断 $dp[n, amt]$ 是否等于 $amt + 1$ ,若是则返回 $-1$ ,代表无法凑出目标金额。
=== "Python"
```python title="coin_change.py"
[class]{}-[func]{coin_change_dp}
```
=== "C++"
```cpp title="coin_change.cpp"
[class]{}-[func]{coinChangeDP}
```
=== "Java"
```java title="coin_change.java"
[class]{coin_change}-[func]{coinChangeDP}
```
=== "C#"
```csharp title="coin_change.cs"
[class]{coin_change}-[func]{CoinChangeDP}
```
=== "Go"
```go title="coin_change.go"
[class]{}-[func]{coinChangeDP}
```
=== "Swift"
```swift title="coin_change.swift"
[class]{}-[func]{coinChangeDP}
```
=== "JS"
```javascript title="coin_change.js"
[class]{}-[func]{coinChangeDP}
```
=== "TS"
```typescript title="coin_change.ts"
[class]{}-[func]{coinChangeDP}
```
=== "Dart"
```dart title="coin_change.dart"
[class]{}-[func]{coinChangeDP}
```
=== "Rust"
```rust title="coin_change.rs"
[class]{}-[func]{coin_change_dp}
```
=== "C"
```c title="coin_change.c"
[class]{}-[func]{coinChangeDP}
```
=== "Zig"
```zig title="coin_change.zig"
[class]{}-[func]{coinChangeDP}
```src
[file]{coin_change}-[class]{}-[func]{coin_change_dp}
```
下图展示了零钱兑换的动态规划过程,和完全背包非常相似。
@ -374,76 +170,8 @@ $$
零钱兑换的空间优化的处理方式和完全背包一致。
=== "Python"
```python title="coin_change.py"
[class]{}-[func]{coin_change_dp_comp}
```
=== "C++"
```cpp title="coin_change.cpp"
[class]{}-[func]{coinChangeDPComp}
```
=== "Java"
```java title="coin_change.java"
[class]{coin_change}-[func]{coinChangeDPComp}
```
=== "C#"
```csharp title="coin_change.cs"
[class]{coin_change}-[func]{CoinChangeDPComp}
```
=== "Go"
```go title="coin_change.go"
[class]{}-[func]{coinChangeDPComp}
```
=== "Swift"
```swift title="coin_change.swift"
[class]{}-[func]{coinChangeDPComp}
```
=== "JS"
```javascript title="coin_change.js"
[class]{}-[func]{coinChangeDPComp}
```
=== "TS"
```typescript title="coin_change.ts"
[class]{}-[func]{coinChangeDPComp}
```
=== "Dart"
```dart title="coin_change.dart"
[class]{}-[func]{coinChangeDPComp}
```
=== "Rust"
```rust title="coin_change.rs"
[class]{}-[func]{coin_change_dp_comp}
```
=== "C"
```c title="coin_change.c"
[class]{}-[func]{coinChangeDPComp}
```
=== "Zig"
```zig title="coin_change.zig"
[class]{}-[func]{coinChangeDPComp}
```src
[file]{coin_change}-[class]{}-[func]{coin_change_dp_comp}
```
## 零钱兑换问题 II
@ -468,150 +196,14 @@ $$
### 代码实现
=== "Python"
```python title="coin_change_ii.py"
[class]{}-[func]{coin_change_ii_dp}
```
=== "C++"
```cpp title="coin_change_ii.cpp"
[class]{}-[func]{coinChangeIIDP}
```
=== "Java"
```java title="coin_change_ii.java"
[class]{coin_change_ii}-[func]{coinChangeIIDP}
```
=== "C#"
```csharp title="coin_change_ii.cs"
[class]{coin_change_ii}-[func]{CoinChangeIIDP}
```
=== "Go"
```go title="coin_change_ii.go"
[class]{}-[func]{coinChangeIIDP}
```
=== "Swift"
```swift title="coin_change_ii.swift"
[class]{}-[func]{coinChangeIIDP}
```
=== "JS"
```javascript title="coin_change_ii.js"
[class]{}-[func]{coinChangeIIDP}
```
=== "TS"
```typescript title="coin_change_ii.ts"
[class]{}-[func]{coinChangeIIDP}
```
=== "Dart"
```dart title="coin_change_ii.dart"
[class]{}-[func]{coinChangeIIDP}
```
=== "Rust"
```rust title="coin_change_ii.rs"
[class]{}-[func]{coin_change_ii_dp}
```
=== "C"
```c title="coin_change_ii.c"
[class]{}-[func]{coinChangeIIDP}
```
=== "Zig"
```zig title="coin_change_ii.zig"
[class]{}-[func]{coinChangeIIDP}
```src
[file]{coin_change_ii}-[class]{}-[func]{coin_change_ii_dp}
```
### 空间优化
空间优化处理方式相同,删除硬币维度即可。
=== "Python"
```python title="coin_change_ii.py"
[class]{}-[func]{coin_change_ii_dp_comp}
```
=== "C++"
```cpp title="coin_change_ii.cpp"
[class]{}-[func]{coinChangeIIDPComp}
```
=== "Java"
```java title="coin_change_ii.java"
[class]{coin_change_ii}-[func]{coinChangeIIDPComp}
```
=== "C#"
```csharp title="coin_change_ii.cs"
[class]{coin_change_ii}-[func]{CoinChangeIIDPComp}
```
=== "Go"
```go title="coin_change_ii.go"
[class]{}-[func]{coinChangeIIDPComp}
```
=== "Swift"
```swift title="coin_change_ii.swift"
[class]{}-[func]{coinChangeIIDPComp}
```
=== "JS"
```javascript title="coin_change_ii.js"
[class]{}-[func]{coinChangeIIDPComp}
```
=== "TS"
```typescript title="coin_change_ii.ts"
[class]{}-[func]{coinChangeIIDPComp}
```
=== "Dart"
```dart title="coin_change_ii.dart"
[class]{}-[func]{coinChangeIIDPComp}
```
=== "Rust"
```rust title="coin_change_ii.rs"
[class]{}-[func]{coin_change_ii_dp_comp}
```
=== "C"
```c title="coin_change_ii.c"
[class]{}-[func]{coinChangeIIDPComp}
```
=== "Zig"
```zig title="coin_change_ii.zig"
[class]{}-[func]{coinChangeIIDPComp}
```src
[file]{coin_change_ii}-[class]{}-[func]{coin_change_ii_dp_comp}
```

View file

@ -28,76 +28,8 @@
以下是基于邻接矩阵表示图的实现代码。
=== "Python"
```python title="graph_adjacency_matrix.py"
[class]{GraphAdjMat}-[func]{}
```
=== "C++"
```cpp title="graph_adjacency_matrix.cpp"
[class]{GraphAdjMat}-[func]{}
```
=== "Java"
```java title="graph_adjacency_matrix.java"
[class]{GraphAdjMat}-[func]{}
```
=== "C#"
```csharp title="graph_adjacency_matrix.cs"
[class]{GraphAdjMat}-[func]{}
```
=== "Go"
```go title="graph_adjacency_matrix.go"
[class]{graphAdjMat}-[func]{}
```
=== "Swift"
```swift title="graph_adjacency_matrix.swift"
[class]{GraphAdjMat}-[func]{}
```
=== "JS"
```javascript title="graph_adjacency_matrix.js"
[class]{GraphAdjMat}-[func]{}
```
=== "TS"
```typescript title="graph_adjacency_matrix.ts"
[class]{GraphAdjMat}-[func]{}
```
=== "Dart"
```dart title="graph_adjacency_matrix.dart"
[class]{GraphAdjMat}-[func]{}
```
=== "Rust"
```rust title="graph_adjacency_matrix.rs"
[class]{GraphAdjMat}-[func]{}
```
=== "C"
```c title="graph_adjacency_matrix.c"
[class]{graphAdjMat}-[func]{}
```
=== "Zig"
```zig title="graph_adjacency_matrix.zig"
```src
[file]{graph_adjacency_matrix}-[class]{graph_adj_mat}-[func]{}
```
## 基于邻接表的实现
@ -131,76 +63,8 @@
2. 如果类似邻接矩阵那样,使用顶点列表索引来区分不同顶点。那么,假设我们想要删除索引为 $i$ 的顶点,则需要遍历整个邻接表,将其中 $> i$ 的索引全部减 $1$ ,这样操作效率较低。
3. 因此我们考虑引入顶点类 `Vertex` ,使得每个顶点都是唯一的对象,此时删除顶点时就无须改动其余顶点了。
=== "Python"
```python title="graph_adjacency_list.py"
[class]{GraphAdjList}-[func]{}
```
=== "C++"
```cpp title="graph_adjacency_list.cpp"
[class]{GraphAdjList}-[func]{}
```
=== "Java"
```java title="graph_adjacency_list.java"
[class]{GraphAdjList}-[func]{}
```
=== "C#"
```csharp title="graph_adjacency_list.cs"
[class]{GraphAdjList}-[func]{}
```
=== "Go"
```go title="graph_adjacency_list.go"
[class]{graphAdjList}-[func]{}
```
=== "Swift"
```swift title="graph_adjacency_list.swift"
[class]{GraphAdjList}-[func]{}
```
=== "JS"
```javascript title="graph_adjacency_list.js"
[class]{GraphAdjList}-[func]{}
```
=== "TS"
```typescript title="graph_adjacency_list.ts"
[class]{GraphAdjList}-[func]{}
```
=== "Dart"
```dart title="graph_adjacency_list.dart"
[class]{GraphAdjList}-[func]{}
```
=== "Rust"
```rust title="graph_adjacency_list.rs"
[class]{GraphAdjList}-[func]{}
```
=== "C"
```c title="graph_adjacency_list.c"
[class]{graphAdjList}-[func]{}
```
=== "Zig"
```zig title="graph_adjacency_list.zig"
[class]{GraphAdjList}-[func]{}
```src
[file]{graph_adjacency_list}-[class]{graph_adj_list}-[func]{}
```
## 效率对比

View file

@ -20,76 +20,8 @@ BFS 通常借助队列来实现。队列具有“先入先出”的性质,这
为了防止重复遍历顶点,我们需要借助一个哈希表 `visited` 来记录哪些节点已被访问。
=== "Python"
```python title="graph_bfs.py"
[class]{}-[func]{graph_bfs}
```
=== "C++"
```cpp title="graph_bfs.cpp"
[class]{}-[func]{graphBFS}
```
=== "Java"
```java title="graph_bfs.java"
[class]{graph_bfs}-[func]{graphBFS}
```
=== "C#"
```csharp title="graph_bfs.cs"
[class]{graph_bfs}-[func]{GraphBFS}
```
=== "Go"
```go title="graph_bfs.go"
[class]{}-[func]{graphBFS}
```
=== "Swift"
```swift title="graph_bfs.swift"
[class]{}-[func]{graphBFS}
```
=== "JS"
```javascript title="graph_bfs.js"
[class]{}-[func]{graphBFS}
```
=== "TS"
```typescript title="graph_bfs.ts"
[class]{}-[func]{graphBFS}
```
=== "Dart"
```dart title="graph_bfs.dart"
[class]{}-[func]{graphBFS}
```
=== "Rust"
```rust title="graph_bfs.rs"
[class]{}-[func]{graph_bfs}
```
=== "C"
```c title="graph_bfs.c"
[class]{}-[func]{graphBFS}
```
=== "Zig"
```zig title="graph_bfs.zig"
[class]{}-[func]{graphBFS}
```src
[file]{graph_bfs}-[class]{}-[func]{graph_bfs}
```
代码相对抽象,建议对照下图来加深理解。
@ -147,100 +79,8 @@ BFS 通常借助队列来实现。队列具有“先入先出”的性质,这
这种“走到尽头再返回”的算法范式通常基于递归来实现。与广度优先遍历类似,在深度优先遍历中我们也需要借助一个哈希表 `visited` 来记录已被访问的顶点,以避免重复访问顶点。
=== "Python"
```python title="graph_dfs.py"
[class]{}-[func]{dfs}
[class]{}-[func]{graph_dfs}
```
=== "C++"
```cpp title="graph_dfs.cpp"
[class]{}-[func]{dfs}
[class]{}-[func]{graphDFS}
```
=== "Java"
```java title="graph_dfs.java"
[class]{graph_dfs}-[func]{dfs}
[class]{graph_dfs}-[func]{graphDFS}
```
=== "C#"
```csharp title="graph_dfs.cs"
[class]{graph_dfs}-[func]{DFS}
[class]{graph_dfs}-[func]{GraphDFS}
```
=== "Go"
```go title="graph_dfs.go"
[class]{}-[func]{dfs}
[class]{}-[func]{graphDFS}
```
=== "Swift"
```swift title="graph_dfs.swift"
[class]{}-[func]{dfs}
[class]{}-[func]{graphDFS}
```
=== "JS"
```javascript title="graph_dfs.js"
[class]{}-[func]{dfs}
[class]{}-[func]{graphDFS}
```
=== "TS"
```typescript title="graph_dfs.ts"
[class]{}-[func]{dfs}
[class]{}-[func]{graphDFS}
```
=== "Dart"
```dart title="graph_dfs.dart"
[class]{}-[func]{dfs}
[class]{}-[func]{graphDFS}
```
=== "Rust"
```rust title="graph_dfs.rs"
[class]{}-[func]{dfs}
[class]{}-[func]{graph_dfs}
```
=== "C"
```c title="graph_dfs.c"
[class]{}-[func]{dfs}
[class]{}-[func]{graphDFS}
```
=== "Zig"
```zig title="graph_dfs.zig"
[class]{}-[func]{dfs}
[class]{}-[func]{graphDFS}
```src
[file]{graph_dfs}-[class]{}-[func]{graph_dfs}
```
深度优先遍历的算法流程如下图所示。

View file

@ -29,100 +29,8 @@
我们建立了一个物品类 `Item` ,以便将物品按照单位价值进行排序。循环进行贪心选择,当背包已满时跳出并返回解。
=== "Python"
```python title="fractional_knapsack.py"
[class]{Item}-[func]{}
[class]{}-[func]{fractional_knapsack}
```
=== "C++"
```cpp title="fractional_knapsack.cpp"
[class]{Item}-[func]{}
[class]{}-[func]{fractionalKnapsack}
```
=== "Java"
```java title="fractional_knapsack.java"
[class]{Item}-[func]{}
[class]{fractional_knapsack}-[func]{fractionalKnapsack}
```
=== "C#"
```csharp title="fractional_knapsack.cs"
[class]{Item}-[func]{}
[class]{fractional_knapsack}-[func]{FractionalKnapsack}
```
=== "Go"
```go title="fractional_knapsack.go"
[class]{Item}-[func]{}
[class]{}-[func]{fractionalKnapsack}
```
=== "Swift"
```swift title="fractional_knapsack.swift"
[class]{Item}-[func]{}
[class]{}-[func]{fractionalKnapsack}
```
=== "JS"
```javascript title="fractional_knapsack.js"
[class]{Item}-[func]{}
[class]{}-[func]{fractionalKnapsack}
```
=== "TS"
```typescript title="fractional_knapsack.ts"
[class]{Item}-[func]{}
[class]{}-[func]{fractionalKnapsack}
```
=== "Dart"
```dart title="fractional_knapsack.dart"
[class]{Item}-[func]{}
[class]{}-[func]{fractionalKnapsack}
```
=== "Rust"
```rust title="fractional_knapsack.rs"
[class]{Item}-[func]{}
[class]{}-[func]{fractional_knapsack}
```
=== "C"
```c title="fractional_knapsack.c"
[class]{Item}-[func]{}
[class]{}-[func]{fractionalKnapsack}
```
=== "Zig"
```zig title="fractional_knapsack.zig"
[class]{Item}-[func]{}
[class]{}-[func]{fractionalKnapsack}
```src
[file]{fractional_knapsack}-[class]{}-[func]{fractional_knapsack}
```
最差情况下,需要遍历整个物品列表,**因此时间复杂度为 $O(n)$** ,其中 $n$ 为物品数量。

View file

@ -19,76 +19,8 @@
实现代码如下所示。你可能会不由地发出感叹So Clean !贪心算法仅用十行代码就解决了零钱兑换问题。
=== "Python"
```python title="coin_change_greedy.py"
[class]{}-[func]{coin_change_greedy}
```
=== "C++"
```cpp title="coin_change_greedy.cpp"
[class]{}-[func]{coinChangeGreedy}
```
=== "Java"
```java title="coin_change_greedy.java"
[class]{coin_change_greedy}-[func]{coinChangeGreedy}
```
=== "C#"
```csharp title="coin_change_greedy.cs"
[class]{coin_change_greedy}-[func]{CoinChangeGreedy}
```
=== "Go"
```go title="coin_change_greedy.go"
[class]{}-[func]{coinChangeGreedy}
```
=== "Swift"
```swift title="coin_change_greedy.swift"
[class]{}-[func]{coinChangeGreedy}
```
=== "JS"
```javascript title="coin_change_greedy.js"
[class]{}-[func]{coinChangeGreedy}
```
=== "TS"
```typescript title="coin_change_greedy.ts"
[class]{}-[func]{coinChangeGreedy}
```
=== "Dart"
```dart title="coin_change_greedy.dart"
[class]{}-[func]{coinChangeGreedy}
```
=== "Rust"
```rust title="coin_change_greedy.rs"
[class]{}-[func]{coin_change_greedy}
```
=== "C"
```c title="coin_change_greedy.c"
[class]{}-[func]{coinChangeGreedy}
```
=== "Zig"
```zig title="coin_change_greedy.zig"
[class]{}-[func]{coinChangeGreedy}
```src
[file]{coin_change_greedy}-[class]{}-[func]{coin_change_greedy}
```
## 贪心优点与局限性

View file

@ -78,76 +78,8 @@ $$
变量 $i$、$j$、$res$ 使用常数大小额外空间,**因此空间复杂度为 $O(1)$** 。
=== "Python"
```python title="max_capacity.py"
[class]{}-[func]{max_capacity}
```
=== "C++"
```cpp title="max_capacity.cpp"
[class]{}-[func]{maxCapacity}
```
=== "Java"
```java title="max_capacity.java"
[class]{max_capacity}-[func]{maxCapacity}
```
=== "C#"
```csharp title="max_capacity.cs"
[class]{max_capacity}-[func]{MaxCapacity}
```
=== "Go"
```go title="max_capacity.go"
[class]{}-[func]{maxCapacity}
```
=== "Swift"
```swift title="max_capacity.swift"
[class]{}-[func]{maxCapacity}
```
=== "JS"
```javascript title="max_capacity.js"
[class]{}-[func]{maxCapacity}
```
=== "TS"
```typescript title="max_capacity.ts"
[class]{}-[func]{maxCapacity}
```
=== "Dart"
```dart title="max_capacity.dart"
[class]{}-[func]{maxCapacity}
```
=== "Rust"
```rust title="max_capacity.rs"
[class]{}-[func]{max_capacity}
```
=== "C"
```c title="max_capacity.c"
[class]{}-[func]{maxCapacity}
```
=== "Zig"
```zig title="max_capacity.zig"
[class]{}-[func]{maxCapacity}
```src
[file]{max_capacity}-[class]{}-[func]{max_capacity}
```
### 正确性证明

View file

@ -63,76 +63,8 @@ $$
请注意,对于 $n \leq 3$ 的边界情况,必须拆分出一个 $1$ ,乘积为 $1 \times (n - 1)$ 。
=== "Python"
```python title="max_product_cutting.py"
[class]{}-[func]{max_product_cutting}
```
=== "C++"
```cpp title="max_product_cutting.cpp"
[class]{}-[func]{maxProductCutting}
```
=== "Java"
```java title="max_product_cutting.java"
[class]{max_product_cutting}-[func]{maxProductCutting}
```
=== "C#"
```csharp title="max_product_cutting.cs"
[class]{max_product_cutting}-[func]{MaxProductCutting}
```
=== "Go"
```go title="max_product_cutting.go"
[class]{}-[func]{maxProductCutting}
```
=== "Swift"
```swift title="max_product_cutting.swift"
[class]{}-[func]{maxProductCutting}
```
=== "JS"
```javascript title="max_product_cutting.js"
[class]{}-[func]{maxProductCutting}
```
=== "TS"
```typescript title="max_product_cutting.ts"
[class]{}-[func]{maxProductCutting}
```
=== "Dart"
```dart title="max_product_cutting.dart"
[class]{}-[func]{maxProductCutting}
```
=== "Rust"
```rust title="max_product_cutting.rs"
[class]{}-[func]{max_product_cutting}
```
=== "C"
```c title="max_product_cutting.c"
[class]{}-[func]{maxProductCutting}
```
=== "Zig"
```zig title="max_product_cutting.zig"
[class]{}-[func]{maxProductCutting}
```src
[file]{max_product_cutting}-[class]{}-[func]{max_product_cutting}
```
![最大切分乘积的计算方法](max_product_cutting_problem.assets/max_product_cutting_greedy_calculation.png)

View file

@ -46,148 +46,8 @@ index = hash(key) % capacity
- **异或哈希**:将输入数据的每个元素通过异或操作累积到一个哈希值中。
- **旋转哈希**:将每个字符的 ASCII 码累积到一个哈希值中,每次累积之前都会对哈希值进行旋转操作。
=== "Python"
```python title="simple_hash.py"
[class]{}-[func]{add_hash}
[class]{}-[func]{mul_hash}
[class]{}-[func]{xor_hash}
[class]{}-[func]{rot_hash}
```
=== "C++"
```cpp title="simple_hash.cpp"
[class]{}-[func]{addHash}
[class]{}-[func]{mulHash}
[class]{}-[func]{xorHash}
[class]{}-[func]{rotHash}
```
=== "Java"
```java title="simple_hash.java"
[class]{simple_hash}-[func]{addHash}
[class]{simple_hash}-[func]{mulHash}
[class]{simple_hash}-[func]{xorHash}
[class]{simple_hash}-[func]{rotHash}
```
=== "C#"
```csharp title="simple_hash.cs"
[class]{simple_hash}-[func]{AddHash}
[class]{simple_hash}-[func]{MulHash}
[class]{simple_hash}-[func]{XorHash}
[class]{simple_hash}-[func]{RotHash}
```
=== "Go"
```go title="simple_hash.go"
[class]{}-[func]{addHash}
[class]{}-[func]{mulHash}
[class]{}-[func]{xorHash}
[class]{}-[func]{rotHash}
```
=== "Swift"
```swift title="simple_hash.swift"
[class]{}-[func]{addHash}
[class]{}-[func]{mulHash}
[class]{}-[func]{xorHash}
[class]{}-[func]{rotHash}
```
=== "JS"
```javascript title="simple_hash.js"
[class]{}-[func]{addHash}
[class]{}-[func]{mulHash}
[class]{}-[func]{xorHash}
[class]{}-[func]{rotHash}
```
=== "TS"
```typescript title="simple_hash.ts"
[class]{}-[func]{addHash}
[class]{}-[func]{mulHash}
[class]{}-[func]{xorHash}
[class]{}-[func]{rotHash}
```
=== "Dart"
```dart title="simple_hash.dart"
[class]{}-[func]{addHash}
[class]{}-[func]{mulHash}
[class]{}-[func]{xorHash}
[class]{}-[func]{rotHash}
```
=== "Rust"
```rust title="simple_hash.rs"
[class]{}-[func]{add_hash}
[class]{}-[func]{mul_hash}
[class]{}-[func]{xor_hash}
[class]{}-[func]{rot_hash}
```
=== "C"
```c title="simple_hash.c"
[class]{}-[func]{addHash}
[class]{}-[func]{mulHash}
[class]{}-[func]{xorHash}
[class]{}-[func]{rotHash}
```
=== "Zig"
```zig title="simple_hash.zig"
[class]{}-[func]{addHash}
[class]{}-[func]{mulHash}
[class]{}-[func]{xorHash}
[class]{}-[func]{rotHash}
```src
[file]{simple_hash}-[class]{}-[func]{rot_hash}
```
观察发现,每种哈希算法的最后一步都是对大质数 $1000000007$ 取模,以确保哈希值在合适的范围内。值得思考的是,为什么要强调对质数取模,或者说对合数取模的弊端是什么?这是一个有趣的问题。

View file

@ -31,78 +31,8 @@
- 使用列表(动态数组)代替链表,从而简化代码。在这种设定下,哈希表(数组)包含多个桶,每个桶都是一个列表。
- 以下实现包含哈希表扩容方法。当负载因子超过 $\frac{2}{3}$ 时,我们将哈希表扩容至 $2$ 倍。
=== "Python"
```python title="hash_map_chaining.py"
[class]{HashMapChaining}-[func]{}
```
=== "C++"
```cpp title="hash_map_chaining.cpp"
[class]{HashMapChaining}-[func]{}
```
=== "Java"
```java title="hash_map_chaining.java"
[class]{HashMapChaining}-[func]{}
```
=== "C#"
```csharp title="hash_map_chaining.cs"
[class]{HashMapChaining}-[func]{}
```
=== "Go"
```go title="hash_map_chaining.go"
[class]{hashMapChaining}-[func]{}
```
=== "Swift"
```swift title="hash_map_chaining.swift"
[class]{HashMapChaining}-[func]{}
```
=== "JS"
```javascript title="hash_map_chaining.js"
[class]{HashMapChaining}-[func]{}
```
=== "TS"
```typescript title="hash_map_chaining.ts"
[class]{HashMapChaining}-[func]{}
```
=== "Dart"
```dart title="hash_map_chaining.dart"
[class]{HashMapChaining}-[func]{}
```
=== "Rust"
```rust title="hash_map_chaining.rs"
[class]{HashMapChaining}-[func]{}
```
=== "C"
```c title="hash_map_chaining.c"
[class]{node}-[func]{}
[class]{hashMapChaining}-[func]{}
```
=== "Zig"
```zig title="hash_map_chaining.zig"
[class]{HashMapChaining}-[func]{}
```src
[file]{hash_map_chaining}-[class]{hash_map_chaining}-[func]{}
```
值得注意的是,当链表很长时,查询效率 $O(n)$ 很差。**此时可以将链表转换为“AVL 树”或“红黑树”**,从而将查询操作的时间复杂度优化至 $O(\log n)$ 。
@ -138,76 +68,8 @@
以下代码实现了一个包含懒删除的开放寻址(线性探测)哈希表。为了更加充分地使用哈希表的空间,我们将哈希表看作是一个“环形数组”,当越过数组尾部时,回到头部继续遍历。
=== "Python"
```python title="hash_map_open_addressing.py"
[class]{HashMapOpenAddressing}-[func]{}
```
=== "C++"
```cpp title="hash_map_open_addressing.cpp"
[class]{HashMapOpenAddressing}-[func]{}
```
=== "Java"
```java title="hash_map_open_addressing.java"
[class]{HashMapOpenAddressing}-[func]{}
```
=== "C#"
```csharp title="hash_map_open_addressing.cs"
[class]{HashMapOpenAddressing}-[func]{}
```
=== "Go"
```go title="hash_map_open_addressing.go"
[class]{hashMapOpenAddressing}-[func]{}
```
=== "Swift"
```swift title="hash_map_open_addressing.swift"
[class]{HashMapOpenAddressing}-[func]{}
```
=== "JS"
```javascript title="hash_map_open_addressing.js"
[class]{HashMapOpenAddressing}-[func]{}
```
=== "TS"
```typescript title="hash_map_open_addressing.ts"
[class]{HashMapOpenAddressing}-[func]{}
```
=== "Dart"
```dart title="hash_map_open_addressing.dart"
[class]{HashMapOpenAddressing}-[func]{}
```
=== "Rust"
```rust title="hash_map_open_addressing.rs"
[class]{HashMapOpenAddressing}-[func]{}
```
=== "C"
```c title="hash_map_open_addressing.c"
[class]{hashMapOpenAddressing}-[func]{}
```
=== "Zig"
```zig title="hash_map_open_addressing.zig"
[class]{HashMapOpenAddressing}-[func]{}
```src
[file]{hash_map_open_addressing}-[class]{hash_map_open_addressing}-[func]{}
```
### 平方探测

View file

@ -491,109 +491,8 @@ index = hash(key) % capacity
以下代码实现了一个简单哈希表。其中,我们将 `key``value` 封装成一个类 `Pair` ,以表示键值对。
=== "Python"
```python title="array_hash_map.py"
[class]{Pair}-[func]{}
[class]{ArrayHashMap}-[func]{}
```
=== "C++"
```cpp title="array_hash_map.cpp"
[class]{Pair}-[func]{}
[class]{ArrayHashMap}-[func]{}
```
=== "Java"
```java title="array_hash_map.java"
[class]{Pair}-[func]{}
[class]{ArrayHashMap}-[func]{}
```
=== "C#"
```csharp title="array_hash_map.cs"
[class]{Pair}-[func]{}
[class]{ArrayHashMap}-[func]{}
```
=== "Go"
```go title="array_hash_map.go"
[class]{pair}-[func]{}
[class]{arrayHashMap}-[func]{}
```
=== "Swift"
```swift title="array_hash_map.swift"
/* 键值对 */
class Pair {
var key: Int
var val: String
init(key: Int, val: String) {
self.key = key
self.val = val
}
}
[class]{ArrayHashMap}-[func]{}
```
=== "JS"
```javascript title="array_hash_map.js"
[class]{Pair}-[func]{}
[class]{ArrayHashMap}-[func]{}
```
=== "TS"
```typescript title="array_hash_map.ts"
[class]{Pair}-[func]{}
[class]{ArrayHashMap}-[func]{}
```
=== "Dart"
```dart title="array_hash_map.dart"
[class]{Pair}-[func]{}
[class]{ArrayHashMap}-[func]{}
```
=== "Rust"
```rust title="array_hash_map.rs"
[class]{Pair}-[func]{}
[class]{ArrayHashMap}-[func]{}
```
=== "C"
```c title="array_hash_map.c"
[class]{pair}-[func]{}
[class]{arrayHashMap}-[func]{}
```
=== "Zig"
```zig title="array_hash_map.zig"
[class]{Pair}-[func]{}
[class]{ArrayHashMap}-[func]{}
```src
[file]{array_hash_map}-[class]{array_hash_map}-[func]{}
```
## 哈希冲突与扩容

View file

@ -23,76 +23,8 @@
值得说明的是,**叶节点没有子节点,天然就是合法的子堆,因此无需堆化**。如以下代码所示,最后一个非叶节点是最后一个节点的父节点,我们从它开始倒序遍历并执行堆化。
=== "Python"
```python title="my_heap.py"
[class]{MaxHeap}-[func]{__init__}
```
=== "C++"
```cpp title="my_heap.cpp"
[class]{MaxHeap}-[func]{MaxHeap}
```
=== "Java"
```java title="my_heap.java"
[class]{MaxHeap}-[func]{MaxHeap}
```
=== "C#"
```csharp title="my_heap.cs"
[class]{MaxHeap}-[func]{MaxHeap}
```
=== "Go"
```go title="my_heap.go"
[class]{maxHeap}-[func]{newMaxHeap}
```
=== "Swift"
```swift title="my_heap.swift"
[class]{MaxHeap}-[func]{init}
```
=== "JS"
```javascript title="my_heap.js"
[class]{MaxHeap}-[func]{constructor}
```
=== "TS"
```typescript title="my_heap.ts"
[class]{MaxHeap}-[func]{constructor}
```
=== "Dart"
```dart title="my_heap.dart"
[class]{MaxHeap}-[func]{MaxHeap}
```
=== "Rust"
```rust title="my_heap.rs"
[class]{MaxHeap}-[func]{new}
```
=== "C"
```c title="my_heap.c"
[class]{maxHeap}-[func]{newMaxHeap}
```
=== "Zig"
```zig title="my_heap.zig"
[class]{MaxHeap}-[func]{init}
```src
[file]{my_heap}-[class]{max_heap}-[func]{__init__}
```
## 复杂度分析

View file

@ -361,200 +361,16 @@
我们可以将索引映射公式封装成函数,方便后续使用。
=== "Python"
```python title="my_heap.py"
[class]{MaxHeap}-[func]{left}
[class]{MaxHeap}-[func]{right}
[class]{MaxHeap}-[func]{parent}
```
=== "C++"
```cpp title="my_heap.cpp"
[class]{MaxHeap}-[func]{left}
[class]{MaxHeap}-[func]{right}
[class]{MaxHeap}-[func]{parent}
```
=== "Java"
```java title="my_heap.java"
[class]{MaxHeap}-[func]{left}
[class]{MaxHeap}-[func]{right}
[class]{MaxHeap}-[func]{parent}
```
=== "C#"
```csharp title="my_heap.cs"
[class]{MaxHeap}-[func]{Left}
[class]{MaxHeap}-[func]{Right}
[class]{MaxHeap}-[func]{Parent}
```
=== "Go"
```go title="my_heap.go"
[class]{maxHeap}-[func]{left}
[class]{maxHeap}-[func]{right}
[class]{maxHeap}-[func]{parent}
```
=== "Swift"
```swift title="my_heap.swift"
[class]{MaxHeap}-[func]{left}
[class]{MaxHeap}-[func]{right}
[class]{MaxHeap}-[func]{parent}
```
=== "JS"
```javascript title="my_heap.js"
[class]{MaxHeap}-[func]{left}
[class]{MaxHeap}-[func]{right}
[class]{MaxHeap}-[func]{parent}
```
=== "TS"
```typescript title="my_heap.ts"
[class]{MaxHeap}-[func]{left}
[class]{MaxHeap}-[func]{right}
[class]{MaxHeap}-[func]{parent}
```
=== "Dart"
```dart title="my_heap.dart"
[class]{MaxHeap}-[func]{_left}
[class]{MaxHeap}-[func]{_right}
[class]{MaxHeap}-[func]{_parent}
```
=== "Rust"
```rust title="my_heap.rs"
[class]{MaxHeap}-[func]{left}
[class]{MaxHeap}-[func]{right}
[class]{MaxHeap}-[func]{parent}
```
=== "C"
```c title="my_heap.c"
[class]{maxHeap}-[func]{left}
[class]{maxHeap}-[func]{right}
[class]{maxHeap}-[func]{parent}
```
=== "Zig"
```zig title="my_heap.zig"
[class]{MaxHeap}-[func]{left}
[class]{MaxHeap}-[func]{right}
[class]{MaxHeap}-[func]{parent}
```src
[file]{my_heap}-[class]{max_heap}-[func]{parent}
```
### 访问堆顶元素
堆顶元素即为二叉树的根节点,也就是列表的首个元素。
=== "Python"
```python title="my_heap.py"
[class]{MaxHeap}-[func]{peek}
```
=== "C++"
```cpp title="my_heap.cpp"
[class]{MaxHeap}-[func]{peek}
```
=== "Java"
```java title="my_heap.java"
[class]{MaxHeap}-[func]{peek}
```
=== "C#"
```csharp title="my_heap.cs"
[class]{MaxHeap}-[func]{Peek}
```
=== "Go"
```go title="my_heap.go"
[class]{maxHeap}-[func]{peek}
```
=== "Swift"
```swift title="my_heap.swift"
[class]{MaxHeap}-[func]{peek}
```
=== "JS"
```javascript title="my_heap.js"
[class]{MaxHeap}-[func]{peek}
```
=== "TS"
```typescript title="my_heap.ts"
[class]{MaxHeap}-[func]{peek}
```
=== "Dart"
```dart title="my_heap.dart"
[class]{MaxHeap}-[func]{peek}
```
=== "Rust"
```rust title="my_heap.rs"
[class]{MaxHeap}-[func]{peek}
```
=== "C"
```c title="my_heap.c"
[class]{maxHeap}-[func]{peek}
```
=== "Zig"
```zig title="my_heap.zig"
[class]{MaxHeap}-[func]{peek}
```src
[file]{my_heap}-[class]{max_heap}-[func]{peek}
```
### 元素入堆
@ -592,100 +408,8 @@
设节点总数为 $n$ ,则树的高度为 $O(\log n)$ 。由此可知,堆化操作的循环轮数最多为 $O(\log n)$ **元素入堆操作的时间复杂度为 $O(\log n)$** 。
=== "Python"
```python title="my_heap.py"
[class]{MaxHeap}-[func]{push}
[class]{MaxHeap}-[func]{sift_up}
```
=== "C++"
```cpp title="my_heap.cpp"
[class]{MaxHeap}-[func]{push}
[class]{MaxHeap}-[func]{siftUp}
```
=== "Java"
```java title="my_heap.java"
[class]{MaxHeap}-[func]{push}
[class]{MaxHeap}-[func]{siftUp}
```
=== "C#"
```csharp title="my_heap.cs"
[class]{MaxHeap}-[func]{Push}
[class]{MaxHeap}-[func]{SiftUp}
```
=== "Go"
```go title="my_heap.go"
[class]{maxHeap}-[func]{push}
[class]{maxHeap}-[func]{siftUp}
```
=== "Swift"
```swift title="my_heap.swift"
[class]{MaxHeap}-[func]{push}
[class]{MaxHeap}-[func]{siftUp}
```
=== "JS"
```javascript title="my_heap.js"
[class]{MaxHeap}-[func]{push}
[class]{MaxHeap}-[func]{siftUp}
```
=== "TS"
```typescript title="my_heap.ts"
[class]{MaxHeap}-[func]{push}
[class]{MaxHeap}-[func]{siftUp}
```
=== "Dart"
```dart title="my_heap.dart"
[class]{MaxHeap}-[func]{push}
[class]{MaxHeap}-[func]{siftUp}
```
=== "Rust"
```rust title="my_heap.rs"
[class]{MaxHeap}-[func]{push}
[class]{MaxHeap}-[func]{sift_up}
```
=== "C"
```c title="my_heap.c"
[class]{maxHeap}-[func]{push}
[class]{maxHeap}-[func]{siftUp}
```
=== "Zig"
```zig title="my_heap.zig"
[class]{MaxHeap}-[func]{push}
[class]{MaxHeap}-[func]{siftUp}
```src
[file]{my_heap}-[class]{max_heap}-[func]{sift_up}
```
### 堆顶元素出堆
@ -730,100 +454,8 @@
与元素入堆操作相似,堆顶元素出堆操作的时间复杂度也为 $O(\log n)$ 。
=== "Python"
```python title="my_heap.py"
[class]{MaxHeap}-[func]{pop}
[class]{MaxHeap}-[func]{sift_down}
```
=== "C++"
```cpp title="my_heap.cpp"
[class]{MaxHeap}-[func]{pop}
[class]{MaxHeap}-[func]{siftDown}
```
=== "Java"
```java title="my_heap.java"
[class]{MaxHeap}-[func]{pop}
[class]{MaxHeap}-[func]{siftDown}
```
=== "C#"
```csharp title="my_heap.cs"
[class]{MaxHeap}-[func]{Pop}
[class]{MaxHeap}-[func]{SiftDown}
```
=== "Go"
```go title="my_heap.go"
[class]{maxHeap}-[func]{pop}
[class]{maxHeap}-[func]{siftDown}
```
=== "Swift"
```swift title="my_heap.swift"
[class]{MaxHeap}-[func]{pop}
[class]{MaxHeap}-[func]{siftDown}
```
=== "JS"
```javascript title="my_heap.js"
[class]{MaxHeap}-[func]{pop}
[class]{MaxHeap}-[func]{siftDown}
```
=== "TS"
```typescript title="my_heap.ts"
[class]{MaxHeap}-[func]{pop}
[class]{MaxHeap}-[func]{siftDown}
```
=== "Dart"
```dart title="my_heap.dart"
[class]{MaxHeap}-[func]{pop}
[class]{MaxHeap}-[func]{siftDown}
```
=== "Rust"
```rust title="my_heap.rs"
[class]{MaxHeap}-[func]{pop}
[class]{MaxHeap}-[func]{sift_down}
```
=== "C"
```c title="my_heap.c"
[class]{maxHeap}-[func]{pop}
[class]{maxHeap}-[func]{siftDown}
```
=== "Zig"
```zig title="my_heap.zig"
[class]{MaxHeap}-[func]{pop}
[class]{MaxHeap}-[func]{siftDown}
```src
[file]{my_heap}-[class]{max_heap}-[func]{sift_down}
```
## 堆常见应用

View file

@ -66,74 +66,6 @@
另外,该方法适用于动态数据流的使用场景。在不断加入数据时,我们可以持续维护堆内的元素,从而实现最大 $k$ 个元素的动态更新。
=== "Python"
```python title="top_k.py"
[class]{}-[func]{top_k_heap}
```
=== "C++"
```cpp title="top_k.cpp"
[class]{}-[func]{topKHeap}
```
=== "Java"
```java title="top_k.java"
[class]{top_k}-[func]{topKHeap}
```
=== "C#"
```csharp title="top_k.cs"
[class]{top_k}-[func]{TopKHeap}
```
=== "Go"
```go title="top_k.go"
[class]{}-[func]{topKHeap}
```
=== "Swift"
```swift title="top_k.swift"
[class]{}-[func]{topKHeap}
```
=== "JS"
```javascript title="top_k.js"
[class]{}-[func]{topKHeap}
```
=== "TS"
```typescript title="top_k.ts"
[class]{}-[func]{topKHeap}
```
=== "Dart"
```dart title="top_k.dart"
[class]{}-[func]{topKHeap}
```
=== "Rust"
```rust title="top_k.rs"
[class]{}-[func]{top_k_heap}
```
=== "C"
```c title="top_k.c"
[class]{}-[func]{topKHeap}
```
=== "Zig"
```zig title="top_k.zig"
[class]{}-[func]{topKHeap}
```src
[file]{top_k}-[class]{}-[func]{top_k_heap}
```

Binary file not shown.

Before

Width:  |  Height:  |  Size: 157 KiB

After

Width:  |  Height:  |  Size: 161 KiB

View file

@ -43,76 +43,8 @@
值得注意的是,由于 $i$ 和 $j$ 都是 `int` 类型,**因此 $i + j$ 可能会超出 `int` 类型的取值范围**。为了避免大数越界,我们通常采用公式 $m = \lfloor {i + (j - i) / 2} \rfloor$ 来计算中点。
=== "Python"
```python title="binary_search.py"
[class]{}-[func]{binary_search}
```
=== "C++"
```cpp title="binary_search.cpp"
[class]{}-[func]{binarySearch}
```
=== "Java"
```java title="binary_search.java"
[class]{binary_search}-[func]{binarySearch}
```
=== "C#"
```csharp title="binary_search.cs"
[class]{binary_search}-[func]{BinarySearch}
```
=== "Go"
```go title="binary_search.go"
[class]{}-[func]{binarySearch}
```
=== "Swift"
```swift title="binary_search.swift"
[class]{}-[func]{binarySearch}
```
=== "JS"
```javascript title="binary_search.js"
[class]{}-[func]{binarySearch}
```
=== "TS"
```typescript title="binary_search.ts"
[class]{}-[func]{binarySearch}
```
=== "Dart"
```dart title="binary_search.dart"
[class]{}-[func]{binarySearch}
```
=== "Rust"
```rust title="binary_search.rs"
[class]{}-[func]{binary_search}
```
=== "C"
```c title="binary_search.c"
[class]{}-[func]{binarySearch}
```
=== "Zig"
```zig title="binary_search.zig"
[class]{}-[func]{binarySearch}
```src
[file]{binary_search}-[class]{}-[func]{binary_search}
```
**时间复杂度 $O(\log n)$** :在二分循环中,区间每轮缩小一半,循环次数为 $\log_2 n$ 。
@ -125,76 +57,8 @@
我们可以基于该表示实现具有相同功能的二分查找算法。
=== "Python"
```python title="binary_search.py"
[class]{}-[func]{binary_search_lcro}
```
=== "C++"
```cpp title="binary_search.cpp"
[class]{}-[func]{binarySearchLCRO}
```
=== "Java"
```java title="binary_search.java"
[class]{binary_search}-[func]{binarySearchLCRO}
```
=== "C#"
```csharp title="binary_search.cs"
[class]{binary_search}-[func]{BinarySearchLCRO}
```
=== "Go"
```go title="binary_search.go"
[class]{}-[func]{binarySearchLCRO}
```
=== "Swift"
```swift title="binary_search.swift"
[class]{}-[func]{binarySearchLCRO}
```
=== "JS"
```javascript title="binary_search.js"
[class]{}-[func]{binarySearchLCRO}
```
=== "TS"
```typescript title="binary_search.ts"
[class]{}-[func]{binarySearchLCRO}
```
=== "Dart"
```dart title="binary_search.dart"
[class]{}-[func]{binarySearchLCRO}
```
=== "Rust"
```rust title="binary_search.rs"
[class]{}-[func]{binary_search_lcro}
```
=== "C"
```c title="binary_search.c"
[class]{}-[func]{binarySearchLCRO}
```
=== "Zig"
```zig title="binary_search.zig"
[class]{}-[func]{binarySearchLCRO}
```src
[file]{binary_search}-[class]{}-[func]{binary_search_lcro}
```
如下图所示,在两种区间表示下,二分查找算法的初始化、循环条件和缩小区间操作皆有所不同。

View file

@ -15,76 +15,8 @@
当遇到以上两种情况时,直接返回 $-1$ 即可。
=== "Python"
```python title="binary_search_edge.py"
[class]{}-[func]{binary_search_left_edge}
```
=== "C++"
```cpp title="binary_search_edge.cpp"
[class]{}-[func]{binarySearchLeftEdge}
```
=== "Java"
```java title="binary_search_edge.java"
[class]{binary_search_edge}-[func]{binarySearchLeftEdge}
```
=== "C#"
```csharp title="binary_search_edge.cs"
[class]{binary_search_edge}-[func]{BinarySearchLeftEdge}
```
=== "Go"
```go title="binary_search_edge.go"
[class]{}-[func]{binarySearchLeftEdge}
```
=== "Swift"
```swift title="binary_search_edge.swift"
[class]{}-[func]{binarySearchLeftEdge}
```
=== "JS"
```javascript title="binary_search_edge.js"
[class]{}-[func]{binarySearchLeftEdge}
```
=== "TS"
```typescript title="binary_search_edge.ts"
[class]{}-[func]{binarySearchLeftEdge}
```
=== "Dart"
```dart title="binary_search_edge.dart"
[class]{}-[func]{binarySearchLeftEdge}
```
=== "Rust"
```rust title="binary_search_edge.rs"
[class]{}-[func]{binary_search_left_edge}
```
=== "C"
```c title="binary_search_edge.c"
[class]{}-[func]{binarySearchLeftEdge}
```
=== "Zig"
```zig title="binary_search_edge.zig"
[class]{}-[func]{binarySearchLeftEdge}
```src
[file]{binary_search_edge}-[class]{}-[func]{binary_search_left_edge}
```
## 查找右边界
@ -103,76 +35,8 @@
请注意,返回的插入点是 $i$ ,因此需要将其减 $1$ ,从而获得 $j$ 。
=== "Python"
```python title="binary_search_edge.py"
[class]{}-[func]{binary_search_right_edge}
```
=== "C++"
```cpp title="binary_search_edge.cpp"
[class]{}-[func]{binarySearchRightEdge}
```
=== "Java"
```java title="binary_search_edge.java"
[class]{binary_search_edge}-[func]{binarySearchRightEdge}
```
=== "C#"
```csharp title="binary_search_edge.cs"
[class]{binary_search_edge}-[func]{BinarySearchRightEdge}
```
=== "Go"
```go title="binary_search_edge.go"
[class]{}-[func]{binarySearchRightEdge}
```
=== "Swift"
```swift title="binary_search_edge.swift"
[class]{}-[func]{binarySearchRightEdge}
```
=== "JS"
```javascript title="binary_search_edge.js"
[class]{}-[func]{binarySearchRightEdge}
```
=== "TS"
```typescript title="binary_search_edge.ts"
[class]{}-[func]{binarySearchRightEdge}
```
=== "Dart"
```dart title="binary_search_edge.dart"
[class]{}-[func]{binarySearchRightEdge}
```
=== "Rust"
```rust title="binary_search_edge.rs"
[class]{}-[func]{binary_search_right_edge}
```
=== "C"
```c title="binary_search_edge.c"
[class]{}-[func]{binarySearchRightEdge}
```
=== "Zig"
```zig title="binary_search_edge.zig"
[class]{}-[func]{binarySearchRightEdge}
```src
[file]{binary_search_edge}-[class]{}-[func]{binary_search_right_edge}
```
### 转化为查找元素

View file

@ -22,76 +22,8 @@
因此二分结束时一定有:$i$ 指向首个大于 `target` 的元素,$j$ 指向首个小于 `target` 的元素。**易得当数组不包含 `target` 时,插入索引为 $i$** 。
=== "Python"
```python title="binary_search_insertion.py"
[class]{}-[func]{binary_search_insertion_simple}
```
=== "C++"
```cpp title="binary_search_insertion.cpp"
[class]{}-[func]{binarySearchInsertionSimple}
```
=== "Java"
```java title="binary_search_insertion.java"
[class]{binary_search_insertion}-[func]{binarySearchInsertionSimple}
```
=== "C#"
```csharp title="binary_search_insertion.cs"
[class]{binary_search_insertion}-[func]{BinarySearchInsertionSimple}
```
=== "Go"
```go title="binary_search_insertion.go"
[class]{}-[func]{binarySearchInsertionSimple}
```
=== "Swift"
```swift title="binary_search_insertion.swift"
[class]{}-[func]{binarySearchInsertionSimple}
```
=== "JS"
```javascript title="binary_search_insertion.js"
[class]{}-[func]{binarySearchInsertionSimple}
```
=== "TS"
```typescript title="binary_search_insertion.ts"
[class]{}-[func]{binarySearchInsertionSimple}
```
=== "Dart"
```dart title="binary_search_insertion.dart"
[class]{}-[func]{binarySearchInsertionSimple}
```
=== "Rust"
```rust title="binary_search_insertion.rs"
[class]{}-[func]{binary_search_insertion}
```
=== "C"
```c title="binary_search_insertion.c"
[class]{}-[func]{binarySearchInsertionSimple}
```
=== "Zig"
```zig title="binary_search_insertion.zig"
[class]{}-[func]{binarySearchInsertionSimple}
```src
[file]{binary_search_insertion}-[class]{}-[func]{binary_search_insertion_simple}
```
## 存在重复元素的情况
@ -146,76 +78,8 @@
即便如此,我们仍然可以将判断条件保持展开,因为其逻辑更加清晰、可读性更好。
=== "Python"
```python title="binary_search_insertion.py"
[class]{}-[func]{binary_search_insertion}
```
=== "C++"
```cpp title="binary_search_insertion.cpp"
[class]{}-[func]{binarySearchInsertion}
```
=== "Java"
```java title="binary_search_insertion.java"
[class]{binary_search_insertion}-[func]{binarySearchInsertion}
```
=== "C#"
```csharp title="binary_search_insertion.cs"
[class]{binary_search_insertion}-[func]{BinarySearchInsertion}
```
=== "Go"
```go title="binary_search_insertion.go"
[class]{}-[func]{binarySearchInsertion}
```
=== "Swift"
```swift title="binary_search_insertion.swift"
[class]{}-[func]{binarySearchInsertion}
```
=== "JS"
```javascript title="binary_search_insertion.js"
[class]{}-[func]{binarySearchInsertion}
```
=== "TS"
```typescript title="binary_search_insertion.ts"
[class]{}-[func]{binarySearchInsertion}
```
=== "Dart"
```dart title="binary_search_insertion.dart"
[class]{}-[func]{binarySearchInsertion}
```
=== "Rust"
```rust title="binary_search_insertion.rs"
[class]{}-[func]{binary_search_insertion}
```
=== "C"
```c title="binary_search_insertion.c"
[class]{}-[func]{binarySearchInsertion}
```
=== "Zig"
```zig title="binary_search_insertion.zig"
[class]{}-[func]{binarySearchInsertion}
```src
[file]{binary_search_insertion}-[class]{}-[func]{binary_search_insertion}
```
!!! tip

View file

@ -12,76 +12,8 @@
![线性查找求解两数之和](replace_linear_by_hashing.assets/two_sum_brute_force.png)
=== "Python"
```python title="two_sum.py"
[class]{}-[func]{two_sum_brute_force}
```
=== "C++"
```cpp title="two_sum.cpp"
[class]{}-[func]{twoSumBruteForce}
```
=== "Java"
```java title="two_sum.java"
[class]{two_sum}-[func]{twoSumBruteForce}
```
=== "C#"
```csharp title="two_sum.cs"
[class]{two_sum}-[func]{TwoSumBruteForce}
```
=== "Go"
```go title="two_sum.go"
[class]{}-[func]{twoSumBruteForce}
```
=== "Swift"
```swift title="two_sum.swift"
[class]{}-[func]{twoSumBruteForce}
```
=== "JS"
```javascript title="two_sum.js"
[class]{}-[func]{twoSumBruteForce}
```
=== "TS"
```typescript title="two_sum.ts"
[class]{}-[func]{twoSumBruteForce}
```
=== "Dart"
```dart title="two_sum.dart"
[class]{}-[func]{twoSumBruteForce}
```
=== "Rust"
```rust title="two_sum.rs"
[class]{}-[func]{two_sum_brute_force}
```
=== "C"
```c title="two_sum.c"
[class]{}-[func]{twoSumBruteForce}
```
=== "Zig"
```zig title="two_sum.zig"
[class]{}-[func]{twoSumBruteForce}
```src
[file]{two_sum}-[class]{}-[func]{two_sum_brute_force}
```
此方法的时间复杂度为 $O(n^2)$ ,空间复杂度为 $O(1)$ ,在大数据量下非常耗时。
@ -104,78 +36,8 @@
实现代码如下所示,仅需单层循环即可。
=== "Python"
```python title="two_sum.py"
[class]{}-[func]{two_sum_hash_table}
```
=== "C++"
```cpp title="two_sum.cpp"
[class]{}-[func]{twoSumHashTable}
```
=== "Java"
```java title="two_sum.java"
[class]{two_sum}-[func]{twoSumHashTable}
```
=== "C#"
```csharp title="two_sum.cs"
[class]{two_sum}-[func]{TwoSumHashTable}
```
=== "Go"
```go title="two_sum.go"
[class]{}-[func]{twoSumHashTable}
```
=== "Swift"
```swift title="two_sum.swift"
[class]{}-[func]{twoSumHashTable}
```
=== "JS"
```javascript title="two_sum.js"
[class]{}-[func]{twoSumHashTable}
```
=== "TS"
```typescript title="two_sum.ts"
[class]{}-[func]{twoSumHashTable}
```
=== "Dart"
```dart title="two_sum.dart"
[class]{}-[func]{twoSumHashTable}
```
=== "Rust"
```rust title="two_sum.rs"
[class]{}-[func]{two_sum_hash_table}
```
=== "C"
```c title="two_sum.c"
[class]{hashTable}-[func]{}
[class]{}-[func]{twoSumHashTable}
```
=== "Zig"
```zig title="two_sum.zig"
[class]{}-[func]{twoSumHashTable}
```src
[file]{two_sum}-[class]{}-[func]{two_sum_hash_table}
```
此方法通过哈希查找将时间复杂度从 $O(n^2)$ 降低至 $O(n)$ ,大幅提升运行效率。

View file

@ -36,76 +36,8 @@
![冒泡排序流程](bubble_sort.assets/bubble_sort_overview.png)
=== "Python"
```python title="bubble_sort.py"
[class]{}-[func]{bubble_sort}
```
=== "C++"
```cpp title="bubble_sort.cpp"
[class]{}-[func]{bubbleSort}
```
=== "Java"
```java title="bubble_sort.java"
[class]{bubble_sort}-[func]{bubbleSort}
```
=== "C#"
```csharp title="bubble_sort.cs"
[class]{bubble_sort}-[func]{BubbleSort}
```
=== "Go"
```go title="bubble_sort.go"
[class]{}-[func]{bubbleSort}
```
=== "Swift"
```swift title="bubble_sort.swift"
[class]{}-[func]{bubbleSort}
```
=== "JS"
```javascript title="bubble_sort.js"
[class]{}-[func]{bubbleSort}
```
=== "TS"
```typescript title="bubble_sort.ts"
[class]{}-[func]{bubbleSort}
```
=== "Dart"
```dart title="bubble_sort.dart"
[class]{}-[func]{bubbleSort}
```
=== "Rust"
```rust title="bubble_sort.rs"
[class]{}-[func]{bubble_sort}
```
=== "C"
```c title="bubble_sort.c"
[class]{}-[func]{bubbleSort}
```
=== "Zig"
```zig title="bubble_sort.zig"
[class]{}-[func]{bubbleSort}
```src
[file]{bubble_sort}-[class]{}-[func]{bubble_sort}
```
## 效率优化
@ -114,76 +46,8 @@
经过优化,冒泡排序的最差和平均时间复杂度仍为 $O(n^2)$ ;但当输入数组完全有序时,可达到最佳时间复杂度 $O(n)$ 。
=== "Python"
```python title="bubble_sort.py"
[class]{}-[func]{bubble_sort_with_flag}
```
=== "C++"
```cpp title="bubble_sort.cpp"
[class]{}-[func]{bubbleSortWithFlag}
```
=== "Java"
```java title="bubble_sort.java"
[class]{bubble_sort}-[func]{bubbleSortWithFlag}
```
=== "C#"
```csharp title="bubble_sort.cs"
[class]{bubble_sort}-[func]{BubbleSortWithFlag}
```
=== "Go"
```go title="bubble_sort.go"
[class]{}-[func]{bubbleSortWithFlag}
```
=== "Swift"
```swift title="bubble_sort.swift"
[class]{}-[func]{bubbleSortWithFlag}
```
=== "JS"
```javascript title="bubble_sort.js"
[class]{}-[func]{bubbleSortWithFlag}
```
=== "TS"
```typescript title="bubble_sort.ts"
[class]{}-[func]{bubbleSortWithFlag}
```
=== "Dart"
```dart title="bubble_sort.dart"
[class]{}-[func]{bubbleSortWithFlag}
```
=== "Rust"
```rust title="bubble_sort.rs"
[class]{}-[func]{bubble_sort_with_flag}
```
=== "C"
```c title="bubble_sort.c"
[class]{}-[func]{bubbleSortWithFlag}
```
=== "Zig"
```zig title="bubble_sort.zig"
[class]{}-[func]{bubbleSortWithFlag}
```src
[file]{bubble_sort}-[class]{}-[func]{bubble_sort_with_flag}
```
## 算法特性

View file

@ -14,76 +14,8 @@
![桶排序算法流程](bucket_sort.assets/bucket_sort_overview.png)
=== "Python"
```python title="bucket_sort.py"
[class]{}-[func]{bucket_sort}
```
=== "C++"
```cpp title="bucket_sort.cpp"
[class]{}-[func]{bucketSort}
```
=== "Java"
```java title="bucket_sort.java"
[class]{bucket_sort}-[func]{bucketSort}
```
=== "C#"
```csharp title="bucket_sort.cs"
[class]{bucket_sort}-[func]{BucketSort}
```
=== "Go"
```go title="bucket_sort.go"
[class]{}-[func]{bucketSort}
```
=== "Swift"
```swift title="bucket_sort.swift"
[class]{}-[func]{bucketSort}
```
=== "JS"
```javascript title="bucket_sort.js"
[class]{}-[func]{bucketSort}
```
=== "TS"
```typescript title="bucket_sort.ts"
[class]{}-[func]{bucketSort}
```
=== "Dart"
```dart title="bucket_sort.dart"
[class]{}-[func]{bucketSort}
```
=== "Rust"
```rust title="bucket_sort.rs"
[class]{}-[func]{bucket_sort}
```
=== "C"
```c title="bucket_sort.c"
[class]{}-[func]{bucketSort}
```
=== "Zig"
```zig title="bucket_sort.zig"
[class]{}-[func]{bucketSort}
```src
[file]{bucket_sort}-[class]{}-[func]{bucket_sort}
```
## 算法特性

View file

@ -12,76 +12,8 @@
![计数排序流程](counting_sort.assets/counting_sort_overview.png)
=== "Python"
```python title="counting_sort.py"
[class]{}-[func]{counting_sort_naive}
```
=== "C++"
```cpp title="counting_sort.cpp"
[class]{}-[func]{countingSortNaive}
```
=== "Java"
```java title="counting_sort.java"
[class]{counting_sort}-[func]{countingSortNaive}
```
=== "C#"
```csharp title="counting_sort.cs"
[class]{counting_sort}-[func]{CountingSortNaive}
```
=== "Go"
```go title="counting_sort.go"
[class]{}-[func]{countingSortNaive}
```
=== "Swift"
```swift title="counting_sort.swift"
[class]{}-[func]{countingSortNaive}
```
=== "JS"
```javascript title="counting_sort.js"
[class]{}-[func]{countingSortNaive}
```
=== "TS"
```typescript title="counting_sort.ts"
[class]{}-[func]{countingSortNaive}
```
=== "Dart"
```dart title="counting_sort.dart"
[class]{}-[func]{countingSortNaive}
```
=== "Rust"
```rust title="counting_sort.rs"
[class]{}-[func]{counting_sort_naive}
```
=== "C"
```c title="counting_sort.c"
[class]{}-[func]{countingSortNaive}
```
=== "Zig"
```zig title="counting_sort.zig"
[class]{}-[func]{countingSortNaive}
```src
[file]{counting_sort}-[class]{}-[func]{counting_sort_naive}
```
!!! note "计数排序与桶排序的联系"
@ -131,76 +63,8 @@ $$
计数排序的实现代码如下所示。
=== "Python"
```python title="counting_sort.py"
[class]{}-[func]{counting_sort}
```
=== "C++"
```cpp title="counting_sort.cpp"
[class]{}-[func]{countingSort}
```
=== "Java"
```java title="counting_sort.java"
[class]{counting_sort}-[func]{countingSort}
```
=== "C#"
```csharp title="counting_sort.cs"
[class]{counting_sort}-[func]{CountingSort}
```
=== "Go"
```go title="counting_sort.go"
[class]{}-[func]{countingSort}
```
=== "Swift"
```swift title="counting_sort.swift"
[class]{}-[func]{countingSort}
```
=== "JS"
```javascript title="counting_sort.js"
[class]{}-[func]{countingSort}
```
=== "TS"
```typescript title="counting_sort.ts"
[class]{}-[func]{countingSort}
```
=== "Dart"
```dart title="counting_sort.dart"
[class]{}-[func]{countingSort}
```
=== "Rust"
```rust title="counting_sort.rs"
[class]{}-[func]{counting_sort}
```
=== "C"
```c title="counting_sort.c"
[class]{}-[func]{countingSort}
```
=== "Zig"
```zig title="counting_sort.zig"
[class]{}-[func]{countingSort}
```src
[file]{counting_sort}-[class]{}-[func]{counting_sort}
```
## 算法特性

View file

@ -62,100 +62,8 @@
在代码实现中,我们使用了与堆章节相同的从顶至底堆化 `sift_down()` 函数。值得注意的是,由于堆的长度会随着提取最大元素而减小,因此我们需要给 `sift_down()` 函数添加一个长度参数 $n$ ,用于指定堆的当前有效长度。
=== "Python"
```python title="heap_sort.py"
[class]{}-[func]{sift_down}
[class]{}-[func]{heap_sort}
```
=== "C++"
```cpp title="heap_sort.cpp"
[class]{}-[func]{siftDown}
[class]{}-[func]{heapSort}
```
=== "Java"
```java title="heap_sort.java"
[class]{heap_sort}-[func]{siftDown}
[class]{heap_sort}-[func]{heapSort}
```
=== "C#"
```csharp title="heap_sort.cs"
[class]{heap_sort}-[func]{SiftDown}
[class]{heap_sort}-[func]{HeapSort}
```
=== "Go"
```go title="heap_sort.go"
[class]{}-[func]{siftDown}
[class]{}-[func]{heapSort}
```
=== "Swift"
```swift title="heap_sort.swift"
[class]{}-[func]{siftDown}
[class]{}-[func]{heapSort}
```
=== "JS"
```javascript title="heap_sort.js"
[class]{}-[func]{siftDown}
[class]{}-[func]{heapSort}
```
=== "TS"
```typescript title="heap_sort.ts"
[class]{}-[func]{siftDown}
[class]{}-[func]{heapSort}
```
=== "Dart"
```dart title="heap_sort.dart"
[class]{}-[func]{siftDown}
[class]{}-[func]{heapSort}
```
=== "Rust"
```rust title="heap_sort.rs"
[class]{}-[func]{sift_down}
[class]{}-[func]{heap_sort}
```
=== "C"
```c title="heap_sort.c"
[class]{}-[func]{siftDown}
[class]{}-[func]{heapSort}
```
=== "Zig"
```zig title="heap_sort.zig"
[class]{}-[func]{siftDown}
[class]{}-[func]{heapSort}
```src
[file]{heap_sort}-[class]{}-[func]{heap_sort}
```
## 算法特性

View file

@ -19,76 +19,8 @@
![插入排序流程](insertion_sort.assets/insertion_sort_overview.png)
=== "Python"
```python title="insertion_sort.py"
[class]{}-[func]{insertion_sort}
```
=== "C++"
```cpp title="insertion_sort.cpp"
[class]{}-[func]{insertionSort}
```
=== "Java"
```java title="insertion_sort.java"
[class]{insertion_sort}-[func]{insertionSort}
```
=== "C#"
```csharp title="insertion_sort.cs"
[class]{insertion_sort}-[func]{InsertionSort}
```
=== "Go"
```go title="insertion_sort.go"
[class]{}-[func]{insertionSort}
```
=== "Swift"
```swift title="insertion_sort.swift"
[class]{}-[func]{insertionSort}
```
=== "JS"
```javascript title="insertion_sort.js"
[class]{}-[func]{insertionSort}
```
=== "TS"
```typescript title="insertion_sort.ts"
[class]{}-[func]{insertionSort}
```
=== "Dart"
```dart title="insertion_sort.dart"
[class]{}-[func]{insertionSort}
```
=== "Rust"
```rust title="insertion_sort.rs"
[class]{}-[func]{insertion_sort}
```
=== "C"
```c title="insertion_sort.c"
[class]{}-[func]{insertionSort}
```
=== "Zig"
```zig title="insertion_sort.zig"
[class]{}-[func]{insertionSort}
```src
[file]{insertion_sort}-[class]{}-[func]{insertion_sort}
```
## 算法特性

View file

@ -51,100 +51,8 @@
- **后序遍历**:先递归左子树,再递归右子树,最后处理根节点。
- **归并排序**:先递归左子数组,再递归右子数组,最后处理合并。
=== "Python"
```python title="merge_sort.py"
[class]{}-[func]{merge}
[class]{}-[func]{merge_sort}
```
=== "C++"
```cpp title="merge_sort.cpp"
[class]{}-[func]{merge}
[class]{}-[func]{mergeSort}
```
=== "Java"
```java title="merge_sort.java"
[class]{merge_sort}-[func]{merge}
[class]{merge_sort}-[func]{mergeSort}
```
=== "C#"
```csharp title="merge_sort.cs"
[class]{merge_sort}-[func]{Merge}
[class]{merge_sort}-[func]{MergeSort}
```
=== "Go"
```go title="merge_sort.go"
[class]{}-[func]{merge}
[class]{}-[func]{mergeSort}
```
=== "Swift"
```swift title="merge_sort.swift"
[class]{}-[func]{merge}
[class]{}-[func]{mergeSort}
```
=== "JS"
```javascript title="merge_sort.js"
[class]{}-[func]{merge}
[class]{}-[func]{mergeSort}
```
=== "TS"
```typescript title="merge_sort.ts"
[class]{}-[func]{merge}
[class]{}-[func]{mergeSort}
```
=== "Dart"
```dart title="merge_sort.dart"
[class]{}-[func]{merge}
[class]{}-[func]{mergeSort}
```
=== "Rust"
```rust title="merge_sort.rs"
[class]{}-[func]{merge}
[class]{}-[func]{merge_sort}
```
=== "C"
```c title="merge_sort.c"
[class]{}-[func]{merge}
[class]{}-[func]{mergeSort}
```
=== "Zig"
```zig title="merge_sort.zig"
[class]{}-[func]{merge}
[class]{}-[func]{mergeSort}
```src
[file]{merge_sort}-[class]{}-[func]{merge_sort}
```
实现合并函数 `merge()` 存在以下难点。

View file

@ -41,94 +41,8 @@
哨兵划分的实质是将一个较长数组的排序问题简化为两个较短数组的排序问题。
=== "Python"
```python title="quick_sort.py"
[class]{QuickSort}-[func]{partition}
```
=== "C++"
```cpp title="quick_sort.cpp"
[class]{QuickSort}-[func]{swap}
[class]{QuickSort}-[func]{partition}
```
=== "Java"
```java title="quick_sort.java"
[class]{QuickSort}-[func]{swap}
[class]{QuickSort}-[func]{partition}
```
=== "C#"
```csharp title="quick_sort.cs"
[class]{quickSort}-[func]{Swap}
[class]{quickSort}-[func]{Partition}
```
=== "Go"
```go title="quick_sort.go"
[class]{quickSort}-[func]{partition}
```
=== "Swift"
```swift title="quick_sort.swift"
[class]{}-[func]{swap}
[class]{}-[func]{partition}
```
=== "JS"
```javascript title="quick_sort.js"
[class]{QuickSort}-[func]{swap}
[class]{QuickSort}-[func]{partition}
```
=== "TS"
```typescript title="quick_sort.ts"
[class]{QuickSort}-[func]{swap}
[class]{QuickSort}-[func]{partition}
```
=== "Dart"
```dart title="quick_sort.dart"
[class]{QuickSort}-[func]{_swap}
[class]{QuickSort}-[func]{_partition}
```
=== "Rust"
```rust title="quick_sort.rs"
[class]{QuickSort}-[func]{partition}
```
=== "C"
```c title="quick_sort.c"
[class]{}-[func]{swap}
[class]{}-[func]{partition}
```
=== "Zig"
```zig title="quick_sort.zig"
[class]{QuickSort}-[func]{swap}
[class]{QuickSort}-[func]{partition}
```src
[file]{quick_sort}-[class]{quick_sort}-[func]{partition}
```
## 算法流程
@ -141,76 +55,8 @@
![快速排序流程](quick_sort.assets/quick_sort_overview.png)
=== "Python"
```python title="quick_sort.py"
[class]{QuickSort}-[func]{quick_sort}
```
=== "C++"
```cpp title="quick_sort.cpp"
[class]{QuickSort}-[func]{quickSort}
```
=== "Java"
```java title="quick_sort.java"
[class]{QuickSort}-[func]{quickSort}
```
=== "C#"
```csharp title="quick_sort.cs"
[class]{quickSort}-[func]{QuickSort}
```
=== "Go"
```go title="quick_sort.go"
[class]{quickSort}-[func]{quickSort}
```
=== "Swift"
```swift title="quick_sort.swift"
[class]{}-[func]{quickSort}
```
=== "JS"
```javascript title="quick_sort.js"
[class]{QuickSort}-[func]{quickSort}
```
=== "TS"
```typescript title="quick_sort.ts"
[class]{QuickSort}-[func]{quickSort}
```
=== "Dart"
```dart title="quick_sort.dart"
[class]{QuickSort}-[func]{quickSort}
```
=== "Rust"
```rust title="quick_sort.rs"
[class]{QuickSort}-[func]{quick_sort}
```
=== "C"
```c title="quick_sort.c"
[class]{}-[func]{quickSort}
```
=== "Zig"
```zig title="quick_sort.zig"
[class]{QuickSort}-[func]{quickSort}
```src
[file]{quick_sort}-[class]{quick_sort}-[func]{quick_sort}
```
## 算法特性
@ -237,100 +83,8 @@
为了进一步改进,我们可以在数组中选取三个候选元素(通常为数组的首、尾、中点元素),**并将这三个候选元素的中位数作为基准数**。这样一来,基准数“既不太小也不太大”的概率将大幅提升。当然,我们还可以选取更多候选元素,以进一步提高算法的稳健性。采用这种方法后,时间复杂度劣化至 $O(n^2)$ 的概率大大降低。
=== "Python"
```python title="quick_sort.py"
[class]{QuickSortMedian}-[func]{median_three}
[class]{QuickSortMedian}-[func]{partition}
```
=== "C++"
```cpp title="quick_sort.cpp"
[class]{QuickSortMedian}-[func]{medianThree}
[class]{QuickSortMedian}-[func]{partition}
```
=== "Java"
```java title="quick_sort.java"
[class]{QuickSortMedian}-[func]{medianThree}
[class]{QuickSortMedian}-[func]{partition}
```
=== "C#"
```csharp title="quick_sort.cs"
[class]{QuickSortMedian}-[func]{MedianThree}
[class]{QuickSortMedian}-[func]{Partition}
```
=== "Go"
```go title="quick_sort.go"
[class]{quickSortMedian}-[func]{medianThree}
[class]{quickSortMedian}-[func]{partition}
```
=== "Swift"
```swift title="quick_sort.swift"
[class]{}-[func]{medianThree}
[class]{}-[func]{partitionMedian}
```
=== "JS"
```javascript title="quick_sort.js"
[class]{QuickSortMedian}-[func]{medianThree}
[class]{QuickSortMedian}-[func]{partition}
```
=== "TS"
```typescript title="quick_sort.ts"
[class]{QuickSortMedian}-[func]{medianThree}
[class]{QuickSortMedian}-[func]{partition}
```
=== "Dart"
```dart title="quick_sort.dart"
[class]{QuickSortMedian}-[func]{_medianThree}
[class]{QuickSortMedian}-[func]{_partition}
```
=== "Rust"
```rust title="quick_sort.rs"
[class]{QuickSortMedian}-[func]{median_three}
[class]{QuickSortMedian}-[func]{partition}
```
=== "C"
```c title="quick_sort.c"
[class]{}-[func]{medianThree}
[class]{}-[func]{partitionMedian}
```
=== "Zig"
```zig title="quick_sort.zig"
[class]{QuickSortMedian}-[func]{medianThree}
[class]{QuickSortMedian}-[func]{partition}
```src
[file]{quick_sort}-[class]{quick_sort_median}-[func]{partition}
```
## 尾递归优化
@ -339,74 +93,6 @@
为了防止栈帧空间的累积,我们可以在每轮哨兵排序完成后,比较两个子数组的长度,**仅对较短的子数组进行递归**。由于较短子数组的长度不会超过 $n / 2$ ,因此这种方法能确保递归深度不超过 $\log n$ ,从而将最差空间复杂度优化至 $O(\log n)$ 。
=== "Python"
```python title="quick_sort.py"
[class]{QuickSortTailCall}-[func]{quick_sort}
```
=== "C++"
```cpp title="quick_sort.cpp"
[class]{QuickSortTailCall}-[func]{quickSort}
```
=== "Java"
```java title="quick_sort.java"
[class]{QuickSortTailCall}-[func]{quickSort}
```
=== "C#"
```csharp title="quick_sort.cs"
[class]{QuickSortTailCall}-[func]{QuickSort}
```
=== "Go"
```go title="quick_sort.go"
[class]{quickSortTailCall}-[func]{quickSort}
```
=== "Swift"
```swift title="quick_sort.swift"
[class]{}-[func]{quickSortTailCall}
```
=== "JS"
```javascript title="quick_sort.js"
[class]{QuickSortTailCall}-[func]{quickSort}
```
=== "TS"
```typescript title="quick_sort.ts"
[class]{QuickSortTailCall}-[func]{quickSort}
```
=== "Dart"
```dart title="quick_sort.dart"
[class]{QuickSortTailCall}-[func]{quickSort}
```
=== "Rust"
```rust title="quick_sort.rs"
[class]{QuickSortTailCall}-[func]{quick_sort}
```
=== "C"
```c title="quick_sort.c"
[class]{}-[func]{quickSortTailCall}
```
=== "Zig"
```zig title="quick_sort.zig"
[class]{QuickSortTailCall}-[func]{quickSort}
```src
[file]{quick_sort}-[class]{quick_sort_tail_call}-[func]{quick_sort}
```

View file

@ -24,124 +24,8 @@ $$
此外,我们需要小幅改动计数排序代码,使之可以根据数字的第 $k$ 位进行排序。
=== "Python"
```python title="radix_sort.py"
[class]{}-[func]{digit}
[class]{}-[func]{counting_sort_digit}
[class]{}-[func]{radix_sort}
```
=== "C++"
```cpp title="radix_sort.cpp"
[class]{}-[func]{digit}
[class]{}-[func]{countingSortDigit}
[class]{}-[func]{radixSort}
```
=== "Java"
```java title="radix_sort.java"
[class]{radix_sort}-[func]{digit}
[class]{radix_sort}-[func]{countingSortDigit}
[class]{radix_sort}-[func]{radixSort}
```
=== "C#"
```csharp title="radix_sort.cs"
[class]{radix_sort}-[func]{Digit}
[class]{radix_sort}-[func]{CountingSortDigit}
[class]{radix_sort}-[func]{RadixSort}
```
=== "Go"
```go title="radix_sort.go"
[class]{}-[func]{digit}
[class]{}-[func]{countingSortDigit}
[class]{}-[func]{radixSort}
```
=== "Swift"
```swift title="radix_sort.swift"
[class]{}-[func]{digit}
[class]{}-[func]{countingSortDigit}
[class]{}-[func]{radixSort}
```
=== "JS"
```javascript title="radix_sort.js"
[class]{}-[func]{digit}
[class]{}-[func]{countingSortDigit}
[class]{}-[func]{radixSort}
```
=== "TS"
```typescript title="radix_sort.ts"
[class]{}-[func]{digit}
[class]{}-[func]{countingSortDigit}
[class]{}-[func]{radixSort}
```
=== "Dart"
```dart title="radix_sort.dart"
[class]{}-[func]{digit}
[class]{}-[func]{countingSortDigit}
[class]{}-[func]{radixSort}
```
=== "Rust"
```rust title="radix_sort.rs"
[class]{}-[func]{digit}
[class]{}-[func]{counting_sort_digit}
[class]{}-[func]{radix_sort}
```
=== "C"
```c title="radix_sort.c"
[class]{}-[func]{digit}
[class]{}-[func]{countingSortDigit}
[class]{}-[func]{radixSort}
```
=== "Zig"
```zig title="radix_sort.zig"
[class]{}-[func]{digit}
[class]{}-[func]{countingSortDigit}
[class]{}-[func]{radixSort}
```src
[file]{radix_sort}-[class]{}-[func]{radix_sort}
```
!!! question "为什么从最低位开始排序?"

View file

@ -45,76 +45,8 @@
在代码中,我们用 $k$ 来记录未排序区间内的最小元素。
=== "Python"
```python title="selection_sort.py"
[class]{}-[func]{selection_sort}
```
=== "C++"
```cpp title="selection_sort.cpp"
[class]{}-[func]{selectionSort}
```
=== "Java"
```java title="selection_sort.java"
[class]{selection_sort}-[func]{selectionSort}
```
=== "C#"
```csharp title="selection_sort.cs"
[class]{selection_sort}-[func]{SelectionSort}
```
=== "Go"
```go title="selection_sort.go"
[class]{}-[func]{selectionSort}
```
=== "Swift"
```swift title="selection_sort.swift"
[class]{}-[func]{selectionSort}
```
=== "JS"
```javascript title="selection_sort.js"
[class]{}-[func]{selectionSort}
```
=== "TS"
```typescript title="selection_sort.ts"
[class]{}-[func]{selectionSort}
```
=== "Dart"
```dart title="selection_sort.dart"
[class]{}-[func]{selectionSort}
```
=== "Rust"
```rust title="selection_sort.rs"
[class]{}-[func]{selection_sort}
```
=== "C"
```c title="selection_sort.c"
[class]{}-[func]{selectionSort}
```
=== "Zig"
```zig title="selection_sort.zig"
[class]{}-[func]{selectionSort}
```src
[file]{selection_sort}-[class]{}-[func]{selection_sort}
```
## 算法特性

View file

@ -371,98 +371,8 @@
实现代码如下所示。
=== "Python"
```python title="linkedlist_deque.py"
[class]{ListNode}-[func]{}
[class]{LinkedListDeque}-[func]{}
```
=== "C++"
```cpp title="linkedlist_deque.cpp"
[class]{DoublyListNode}-[func]{}
[class]{LinkedListDeque}-[func]{}
```
=== "Java"
```java title="linkedlist_deque.java"
[class]{ListNode}-[func]{}
[class]{LinkedListDeque}-[func]{}
```
=== "C#"
```csharp title="linkedlist_deque.cs"
[class]{ListNode}-[func]{}
[class]{LinkedListDeque}-[func]{}
```
=== "Go"
```go title="linkedlist_deque.go"
[class]{linkedListDeque}-[func]{}
```
=== "Swift"
```swift title="linkedlist_deque.swift"
[class]{ListNode}-[func]{}
[class]{LinkedListDeque}-[func]{}
```
=== "JS"
```javascript title="linkedlist_deque.js"
[class]{ListNode}-[func]{}
[class]{LinkedListDeque}-[func]{}
```
=== "TS"
```typescript title="linkedlist_deque.ts"
[class]{ListNode}-[func]{}
[class]{LinkedListDeque}-[func]{}
```
=== "Dart"
```dart title="linkedlist_deque.dart"
[class]{ListNode}-[func]{}
[class]{LinkedListDeque}-[func]{}
```
=== "Rust"
```rust title="linkedlist_deque.rs"
[class]{ListNode}-[func]{}
[class]{LinkedListDeque}-[func]{}
```
=== "C"
```c title="linkedlist_deque.c"
[class]{doublyListNode}-[func]{}
[class]{linkedListDeque}-[func]{}
```
=== "Zig"
```zig title="linkedlist_deque.zig"
[class]{ListNode}-[func]{}
[class]{LinkedListDeque}-[func]{}
```src
[file]{linkedlist_deque}-[class]{linked_list_deque}-[func]{}
```
### 基于数组的实现
@ -486,76 +396,8 @@
在队列的实现基础上,仅需增加“队首入队”和“队尾出队”的方法。
=== "Python"
```python title="array_deque.py"
[class]{ArrayDeque}-[func]{}
```
=== "C++"
```cpp title="array_deque.cpp"
[class]{ArrayDeque}-[func]{}
```
=== "Java"
```java title="array_deque.java"
[class]{ArrayDeque}-[func]{}
```
=== "C#"
```csharp title="array_deque.cs"
[class]{ArrayDeque}-[func]{}
```
=== "Go"
```go title="array_deque.go"
[class]{arrayDeque}-[func]{}
```
=== "Swift"
```swift title="array_deque.swift"
[class]{ArrayDeque}-[func]{}
```
=== "JS"
```javascript title="array_deque.js"
[class]{ArrayDeque}-[func]{}
```
=== "TS"
```typescript title="array_deque.ts"
[class]{ArrayDeque}-[func]{}
```
=== "Dart"
```dart title="array_deque.dart"
[class]{ArrayDeque}-[func]{}
```
=== "Rust"
```rust title="array_deque.rs"
[class]{ArrayDeque}-[func]{}
```
=== "C"
```c title="array_deque.c"
[class]{arrayDeque}-[func]{}
```
=== "Zig"
```zig title="array_deque.zig"
[class]{ArrayDeque}-[func]{}
```src
[file]{array_deque}-[class]{array_deque}-[func]{}
```
## 双向队列应用

View file

@ -325,76 +325,8 @@
以下是用链表实现队列的代码。
=== "Python"
```python title="linkedlist_queue.py"
[class]{LinkedListQueue}-[func]{}
```
=== "C++"
```cpp title="linkedlist_queue.cpp"
[class]{LinkedListQueue}-[func]{}
```
=== "Java"
```java title="linkedlist_queue.java"
[class]{LinkedListQueue}-[func]{}
```
=== "C#"
```csharp title="linkedlist_queue.cs"
[class]{LinkedListQueue}-[func]{}
```
=== "Go"
```go title="linkedlist_queue.go"
[class]{linkedListQueue}-[func]{}
```
=== "Swift"
```swift title="linkedlist_queue.swift"
[class]{LinkedListQueue}-[func]{}
```
=== "JS"
```javascript title="linkedlist_queue.js"
[class]{LinkedListQueue}-[func]{}
```
=== "TS"
```typescript title="linkedlist_queue.ts"
[class]{LinkedListQueue}-[func]{}
```
=== "Dart"
```dart title="linkedlist_queue.dart"
[class]{LinkedListQueue}-[func]{}
```
=== "Rust"
```rust title="linkedlist_queue.rs"
[class]{LinkedListQueue}-[func]{}
```
=== "C"
```c title="linkedlist_queue.c"
[class]{linkedListQueue}-[func]{}
```
=== "Zig"
```zig title="linkedlist_queue.zig"
[class]{LinkedListQueue}-[func]{}
```src
[file]{linkedlist_queue}-[class]{linked_list_queue}-[func]{}
```
### 基于数组的实现
@ -423,76 +355,8 @@
对于环形数组,我们需要让 `front``rear` 在越过数组尾部时,直接回到数组头部继续遍历。这种周期性规律可以通过“取余操作”来实现,代码如下所示。
=== "Python"
```python title="array_queue.py"
[class]{ArrayQueue}-[func]{}
```
=== "C++"
```cpp title="array_queue.cpp"
[class]{ArrayQueue}-[func]{}
```
=== "Java"
```java title="array_queue.java"
[class]{ArrayQueue}-[func]{}
```
=== "C#"
```csharp title="array_queue.cs"
[class]{ArrayQueue}-[func]{}
```
=== "Go"
```go title="array_queue.go"
[class]{arrayQueue}-[func]{}
```
=== "Swift"
```swift title="array_queue.swift"
[class]{ArrayQueue}-[func]{}
```
=== "JS"
```javascript title="array_queue.js"
[class]{ArrayQueue}-[func]{}
```
=== "TS"
```typescript title="array_queue.ts"
[class]{ArrayQueue}-[func]{}
```
=== "Dart"
```dart title="array_queue.dart"
[class]{ArrayQueue}-[func]{}
```
=== "Rust"
```rust title="array_queue.rs"
[class]{ArrayQueue}-[func]{}
```
=== "C"
```c title="array_queue.c"
[class]{arrayQueue}-[func]{}
```
=== "Zig"
```zig title="array_queue.zig"
[class]{ArrayQueue}-[func]{}
```src
[file]{array_queue}-[class]{array_queue}-[func]{}
```
以上实现的队列仍然具有局限性,即其长度不可变。然而,这个问题不难解决,我们可以将数组替换为动态数组,从而引入扩容机制。有兴趣的同学可以尝试自行实现。

View file

@ -325,76 +325,8 @@
以下是基于链表实现栈的示例代码。
=== "Python"
```python title="linkedlist_stack.py"
[class]{LinkedListStack}-[func]{}
```
=== "C++"
```cpp title="linkedlist_stack.cpp"
[class]{LinkedListStack}-[func]{}
```
=== "Java"
```java title="linkedlist_stack.java"
[class]{LinkedListStack}-[func]{}
```
=== "C#"
```csharp title="linkedlist_stack.cs"
[class]{LinkedListStack}-[func]{}
```
=== "Go"
```go title="linkedlist_stack.go"
[class]{linkedListStack}-[func]{}
```
=== "Swift"
```swift title="linkedlist_stack.swift"
[class]{LinkedListStack}-[func]{}
```
=== "JS"
```javascript title="linkedlist_stack.js"
[class]{LinkedListStack}-[func]{}
```
=== "TS"
```typescript title="linkedlist_stack.ts"
[class]{LinkedListStack}-[func]{}
```
=== "Dart"
```dart title="linkedlist_stack.dart"
[class]{LinkedListStack}-[func]{}
```
=== "Rust"
```rust title="linkedlist_stack.rs"
[class]{LinkedListStack}-[func]{}
```
=== "C"
```c title="linkedlist_stack.c"
[class]{linkedListStack}-[func]{}
```
=== "Zig"
```zig title="linkedlist_stack.zig"
[class]{LinkedListStack}-[func]{}
```src
[file]{linkedlist_stack}-[class]{linked_list_stack}-[func]{}
```
### 基于数组的实现
@ -412,76 +344,8 @@
由于入栈的元素可能会源源不断地增加,因此我们可以使用动态数组,这样就无须自行处理数组扩容问题。以下为示例代码。
=== "Python"
```python title="array_stack.py"
[class]{ArrayStack}-[func]{}
```
=== "C++"
```cpp title="array_stack.cpp"
[class]{ArrayStack}-[func]{}
```
=== "Java"
```java title="array_stack.java"
[class]{ArrayStack}-[func]{}
```
=== "C#"
```csharp title="array_stack.cs"
[class]{ArrayStack}-[func]{}
```
=== "Go"
```go title="array_stack.go"
[class]{arrayStack}-[func]{}
```
=== "Swift"
```swift title="array_stack.swift"
[class]{ArrayStack}-[func]{}
```
=== "JS"
```javascript title="array_stack.js"
[class]{ArrayStack}-[func]{}
```
=== "TS"
```typescript title="array_stack.ts"
[class]{ArrayStack}-[func]{}
```
=== "Dart"
```dart title="array_stack.dart"
[class]{ArrayStack}-[func]{}
```
=== "Rust"
```rust title="array_stack.rs"
[class]{ArrayStack}-[func]{}
```
=== "C"
```c title="array_stack.c"
[class]{arrayStack}-[func]{}
```
=== "Zig"
```zig title="array_stack.zig"
[class]{ArrayStack}-[func]{}
```src
[file]{array_stack}-[class]{array_stack}-[func]{}
```
## 两种实现对比

View file

@ -131,76 +131,8 @@
- 给定某节点,获取它的值、左(右)子节点、父节点。
- 获取前序遍历、中序遍历、后序遍历、层序遍历序列。
=== "Python"
```python title="array_binary_tree.py"
[class]{ArrayBinaryTree}-[func]{}
```
=== "C++"
```cpp title="array_binary_tree.cpp"
[class]{ArrayBinaryTree}-[func]{}
```
=== "Java"
```java title="array_binary_tree.java"
[class]{ArrayBinaryTree}-[func]{}
```
=== "C#"
```csharp title="array_binary_tree.cs"
[class]{ArrayBinaryTree}-[func]{}
```
=== "Go"
```go title="array_binary_tree.go"
[class]{arrayBinaryTree}-[func]{}
```
=== "Swift"
```swift title="array_binary_tree.swift"
[class]{ArrayBinaryTree}-[func]{}
```
=== "JS"
```javascript title="array_binary_tree.js"
[class]{ArrayBinaryTree}-[func]{}
```
=== "TS"
```typescript title="array_binary_tree.ts"
[class]{ArrayBinaryTree}-[func]{}
```
=== "Dart"
```dart title="array_binary_tree.dart"
[class]{ArrayBinaryTree}-[func]{}
```
=== "Rust"
```rust title="array_binary_tree.rs"
[class]{ArrayBinaryTree}-[func]{}
```
=== "C"
```c title="array_binary_tree.c"
[class]{arrayBinaryTree}-[func]{}
```
=== "Zig"
```zig title="array_binary_tree.zig"
[class]{ArrayBinaryTree}-[func]{}
```src
[file]{array_binary_tree}-[class]{array_binary_tree}-[func]{}
```
## 优势与局限性

View file

@ -211,176 +211,16 @@ AVL 树既是二叉搜索树也是平衡二叉树,同时满足这两类二叉
“节点高度”是指从该节点到最远叶节点的距离,即所经过的“边”的数量。需要特别注意的是,叶节点的高度为 0 ,而空节点的高度为 -1 。我们将创建两个工具函数,分别用于获取和更新节点的高度。
=== "Python"
```python title="avl_tree.py"
[class]{AVLTree}-[func]{height}
[class]{AVLTree}-[func]{update_height}
```
=== "C++"
```cpp title="avl_tree.cpp"
[class]{AVLTree}-[func]{height}
[class]{AVLTree}-[func]{updateHeight}
```
=== "Java"
```java title="avl_tree.java"
[class]{AVLTree}-[func]{height}
[class]{AVLTree}-[func]{updateHeight}
```
=== "C#"
```csharp title="avl_tree.cs"
[class]{AVLTree}-[func]{Height}
[class]{AVLTree}-[func]{UpdateHeight}
```
=== "Go"
```go title="avl_tree.go"
[class]{aVLTree}-[func]{height}
[class]{aVLTree}-[func]{updateHeight}
```
=== "Swift"
```swift title="avl_tree.swift"
[class]{AVLTree}-[func]{height}
[class]{AVLTree}-[func]{updateHeight}
```
=== "JS"
```javascript title="avl_tree.js"
[class]{AVLTree}-[func]{height}
[class]{AVLTree}-[func]{updateHeight}
```
=== "TS"
```typescript title="avl_tree.ts"
[class]{AVLTree}-[func]{height}
[class]{AVLTree}-[func]{updateHeight}
```
=== "Dart"
```dart title="avl_tree.dart"
[class]{AVLTree}-[func]{height}
[class]{AVLTree}-[func]{updateHeight}
```
=== "Rust"
```rust title="avl_tree.rs"
[class]{AVLTree}-[func]{height}
[class]{AVLTree}-[func]{update_height}
```
=== "C"
```c title="avl_tree.c"
[class]{}-[func]{height}
[class]{}-[func]{updateHeight}
```
=== "Zig"
```zig title="avl_tree.zig"
[class]{AVLTree}-[func]{height}
[class]{AVLTree}-[func]{updateHeight}
```src
[file]{avl_tree}-[class]{a_v_l_tree}-[func]{update_height}
```
### 节点平衡因子
节点的「平衡因子 balance factor」定义为节点左子树的高度减去右子树的高度同时规定空节点的平衡因子为 0 。我们同样将获取节点平衡因子的功能封装成函数,方便后续使用。
=== "Python"
```python title="avl_tree.py"
[class]{AVLTree}-[func]{balance_factor}
```
=== "C++"
```cpp title="avl_tree.cpp"
[class]{AVLTree}-[func]{balanceFactor}
```
=== "Java"
```java title="avl_tree.java"
[class]{AVLTree}-[func]{balanceFactor}
```
=== "C#"
```csharp title="avl_tree.cs"
[class]{AVLTree}-[func]{BalanceFactor}
```
=== "Go"
```go title="avl_tree.go"
[class]{aVLTree}-[func]{balanceFactor}
```
=== "Swift"
```swift title="avl_tree.swift"
[class]{AVLTree}-[func]{balanceFactor}
```
=== "JS"
```javascript title="avl_tree.js"
[class]{AVLTree}-[func]{balanceFactor}
```
=== "TS"
```typescript title="avl_tree.ts"
[class]{AVLTree}-[func]{balanceFactor}
```
=== "Dart"
```dart title="avl_tree.dart"
[class]{AVLTree}-[func]{balanceFactor}
```
=== "Rust"
```rust title="avl_tree.rs"
[class]{AVLTree}-[func]{balance_factor}
```
=== "C"
```c title="avl_tree.c"
[class]{}-[func]{balanceFactor}
```
=== "Zig"
```zig title="avl_tree.zig"
[class]{AVLTree}-[func]{balanceFactor}
```src
[file]{avl_tree}-[class]{a_v_l_tree}-[func]{balance_factor}
```
!!! note
@ -415,76 +255,8 @@ AVL 树的特点在于“旋转”操作,它能够在不影响二叉树的中
“向右旋转”是一种形象化的说法,实际上需要通过修改节点指针来实现,代码如下所示。
=== "Python"
```python title="avl_tree.py"
[class]{AVLTree}-[func]{right_rotate}
```
=== "C++"
```cpp title="avl_tree.cpp"
[class]{AVLTree}-[func]{rightRotate}
```
=== "Java"
```java title="avl_tree.java"
[class]{AVLTree}-[func]{rightRotate}
```
=== "C#"
```csharp title="avl_tree.cs"
[class]{AVLTree}-[func]{RightRotate}
```
=== "Go"
```go title="avl_tree.go"
[class]{aVLTree}-[func]{rightRotate}
```
=== "Swift"
```swift title="avl_tree.swift"
[class]{AVLTree}-[func]{rightRotate}
```
=== "JS"
```javascript title="avl_tree.js"
[class]{AVLTree}-[func]{rightRotate}
```
=== "TS"
```typescript title="avl_tree.ts"
[class]{AVLTree}-[func]{rightRotate}
```
=== "Dart"
```dart title="avl_tree.dart"
[class]{AVLTree}-[func]{rightRotate}
```
=== "Rust"
```rust title="avl_tree.rs"
[class]{AVLTree}-[func]{right_rotate}
```
=== "C"
```c title="avl_tree.c"
[class]{}-[func]{rightRotate}
```
=== "Zig"
```zig title="avl_tree.zig"
[class]{AVLTree}-[func]{rightRotate}
```src
[file]{avl_tree}-[class]{a_v_l_tree}-[func]{right_rotate}
```
### 左旋
@ -499,76 +271,8 @@ AVL 树的特点在于“旋转”操作,它能够在不影响二叉树的中
可以观察到,**右旋和左旋操作在逻辑上是镜像对称的,它们分别解决的两种失衡情况也是对称的**。基于对称性,我们只需将右旋的实现代码中的所有的 `left` 替换为 `right` ,将所有的 `right` 替换为 `left` ,即可得到左旋的实现代码。
=== "Python"
```python title="avl_tree.py"
[class]{AVLTree}-[func]{left_rotate}
```
=== "C++"
```cpp title="avl_tree.cpp"
[class]{AVLTree}-[func]{leftRotate}
```
=== "Java"
```java title="avl_tree.java"
[class]{AVLTree}-[func]{leftRotate}
```
=== "C#"
```csharp title="avl_tree.cs"
[class]{AVLTree}-[func]{LeftRotate}
```
=== "Go"
```go title="avl_tree.go"
[class]{aVLTree}-[func]{leftRotate}
```
=== "Swift"
```swift title="avl_tree.swift"
[class]{AVLTree}-[func]{leftRotate}
```
=== "JS"
```javascript title="avl_tree.js"
[class]{AVLTree}-[func]{leftRotate}
```
=== "TS"
```typescript title="avl_tree.ts"
[class]{AVLTree}-[func]{leftRotate}
```
=== "Dart"
```dart title="avl_tree.dart"
[class]{AVLTree}-[func]{leftRotate}
```
=== "Rust"
```rust title="avl_tree.rs"
[class]{AVLTree}-[func]{left_rotate}
```
=== "C"
```c title="avl_tree.c"
[class]{}-[func]{leftRotate}
```
=== "Zig"
```zig title="avl_tree.zig"
[class]{AVLTree}-[func]{leftRotate}
```src
[file]{avl_tree}-[class]{a_v_l_tree}-[func]{left_rotate}
```
### 先左旋后右旋
@ -602,76 +306,8 @@ AVL 树的特点在于“旋转”操作,它能够在不影响二叉树的中
为了便于使用,我们将旋转操作封装成一个函数。**有了这个函数,我们就能对各种失衡情况进行旋转,使失衡节点重新恢复平衡**。
=== "Python"
```python title="avl_tree.py"
[class]{AVLTree}-[func]{rotate}
```
=== "C++"
```cpp title="avl_tree.cpp"
[class]{AVLTree}-[func]{rotate}
```
=== "Java"
```java title="avl_tree.java"
[class]{AVLTree}-[func]{rotate}
```
=== "C#"
```csharp title="avl_tree.cs"
[class]{AVLTree}-[func]{Rotate}
```
=== "Go"
```go title="avl_tree.go"
[class]{aVLTree}-[func]{rotate}
```
=== "Swift"
```swift title="avl_tree.swift"
[class]{AVLTree}-[func]{rotate}
```
=== "JS"
```javascript title="avl_tree.js"
[class]{AVLTree}-[func]{rotate}
```
=== "TS"
```typescript title="avl_tree.ts"
[class]{AVLTree}-[func]{rotate}
```
=== "Dart"
```dart title="avl_tree.dart"
[class]{AVLTree}-[func]{rotate}
```
=== "Rust"
```rust title="avl_tree.rs"
[class]{AVLTree}-[func]{rotate}
```
=== "C"
```c title="avl_tree.c"
[class]{}-[func]{rotate}
```
=== "Zig"
```zig title="avl_tree.zig"
[class]{AVLTree}-[func]{rotate}
```src
[file]{avl_tree}-[class]{a_v_l_tree}-[func]{rotate}
```
## AVL 树常用操作
@ -680,200 +316,16 @@ AVL 树的特点在于“旋转”操作,它能够在不影响二叉树的中
AVL 树的节点插入操作与二叉搜索树在主体上类似。唯一的区别在于,在 AVL 树中插入节点后,从该节点到根节点的路径上可能会出现一系列失衡节点。因此,**我们需要从这个节点开始,自底向上执行旋转操作,使所有失衡节点恢复平衡**。
=== "Python"
```python title="avl_tree.py"
[class]{AVLTree}-[func]{insert}
[class]{AVLTree}-[func]{insert_helper}
```
=== "C++"
```cpp title="avl_tree.cpp"
[class]{AVLTree}-[func]{insert}
[class]{AVLTree}-[func]{insertHelper}
```
=== "Java"
```java title="avl_tree.java"
[class]{AVLTree}-[func]{insert}
[class]{AVLTree}-[func]{insertHelper}
```
=== "C#"
```csharp title="avl_tree.cs"
[class]{AVLTree}-[func]{Insert}
[class]{AVLTree}-[func]{InsertHelper}
```
=== "Go"
```go title="avl_tree.go"
[class]{aVLTree}-[func]{insert}
[class]{aVLTree}-[func]{insertHelper}
```
=== "Swift"
```swift title="avl_tree.swift"
[class]{AVLTree}-[func]{insert}
[class]{AVLTree}-[func]{insertHelper}
```
=== "JS"
```javascript title="avl_tree.js"
[class]{AVLTree}-[func]{insert}
[class]{AVLTree}-[func]{insertHelper}
```
=== "TS"
```typescript title="avl_tree.ts"
[class]{AVLTree}-[func]{insert}
[class]{AVLTree}-[func]{insertHelper}
```
=== "Dart"
```dart title="avl_tree.dart"
[class]{AVLTree}-[func]{insert}
[class]{AVLTree}-[func]{insertHelper}
```
=== "Rust"
```rust title="avl_tree.rs"
[class]{AVLTree}-[func]{insert}
[class]{AVLTree}-[func]{insert_helper}
```
=== "C"
```c title="avl_tree.c"
[class]{aVLTree}-[func]{insert}
[class]{}-[func]{insertHelper}
```
=== "Zig"
```zig title="avl_tree.zig"
[class]{AVLTree}-[func]{insert}
[class]{AVLTree}-[func]{insertHelper}
```src
[file]{avl_tree}-[class]{a_v_l_tree}-[func]{insert_helper}
```
### 删除节点
类似地,在二叉搜索树的删除节点方法的基础上,需要从底至顶地执行旋转操作,使所有失衡节点恢复平衡。
=== "Python"
```python title="avl_tree.py"
[class]{AVLTree}-[func]{remove}
[class]{AVLTree}-[func]{remove_helper}
```
=== "C++"
```cpp title="avl_tree.cpp"
[class]{AVLTree}-[func]{remove}
[class]{AVLTree}-[func]{removeHelper}
```
=== "Java"
```java title="avl_tree.java"
[class]{AVLTree}-[func]{remove}
[class]{AVLTree}-[func]{removeHelper}
```
=== "C#"
```csharp title="avl_tree.cs"
[class]{AVLTree}-[func]{Remove}
[class]{AVLTree}-[func]{RemoveHelper}
```
=== "Go"
```go title="avl_tree.go"
[class]{aVLTree}-[func]{remove}
[class]{aVLTree}-[func]{removeHelper}
```
=== "Swift"
```swift title="avl_tree.swift"
[class]{AVLTree}-[func]{remove}
[class]{AVLTree}-[func]{removeHelper}
```
=== "JS"
```javascript title="avl_tree.js"
[class]{AVLTree}-[func]{remove}
[class]{AVLTree}-[func]{removeHelper}
```
=== "TS"
```typescript title="avl_tree.ts"
[class]{AVLTree}-[func]{remove}
[class]{AVLTree}-[func]{removeHelper}
```
=== "Dart"
```dart title="avl_tree.dart"
[class]{AVLTree}-[func]{remove}
[class]{AVLTree}-[func]{removeHelper}
```
=== "Rust"
```rust title="avl_tree.rs"
[class]{AVLTree}-[func]{remove}
[class]{AVLTree}-[func]{remove_helper}
```
=== "C"
```c title="avl_tree.c"
[class]{aVLTree}-[func]{removeItem}
[class]{}-[func]{removeHelper}
```
=== "Zig"
```zig title="avl_tree.zig"
[class]{AVLTree}-[func]{remove}
[class]{AVLTree}-[func]{removeHelper}
```src
[file]{avl_tree}-[class]{a_v_l_tree}-[func]{remove_helper}
```
### 查找节点

View file

@ -33,76 +33,8 @@
二叉搜索树的查找操作与二分查找算法的工作原理一致,都是每轮排除一半情况。循环次数最多为二叉树的高度,当二叉树平衡时,使用 $O(\log n)$ 时间。
=== "Python"
```python title="binary_search_tree.py"
[class]{BinarySearchTree}-[func]{search}
```
=== "C++"
```cpp title="binary_search_tree.cpp"
[class]{BinarySearchTree}-[func]{search}
```
=== "Java"
```java title="binary_search_tree.java"
[class]{BinarySearchTree}-[func]{search}
```
=== "C#"
```csharp title="binary_search_tree.cs"
[class]{BinarySearchTree}-[func]{Search}
```
=== "Go"
```go title="binary_search_tree.go"
[class]{binarySearchTree}-[func]{search}
```
=== "Swift"
```swift title="binary_search_tree.swift"
[class]{BinarySearchTree}-[func]{search}
```
=== "JS"
```javascript title="binary_search_tree.js"
[class]{BinarySearchTree}-[func]{search}
```
=== "TS"
```typescript title="binary_search_tree.ts"
[class]{BinarySearchTree}-[func]{search}
```
=== "Dart"
```dart title="binary_search_tree.dart"
[class]{BinarySearchTree}-[func]{search}
```
=== "Rust"
```rust title="binary_search_tree.rs"
[class]{BinarySearchTree}-[func]{search}
```
=== "C"
```c title="binary_search_tree.c"
[class]{binarySearchTree}-[func]{search}
```
=== "Zig"
```zig title="binary_search_tree.zig"
[class]{BinarySearchTree}-[func]{search}
```src
[file]{binary_search_tree}-[class]{binary_search_tree}-[func]{search}
```
### 插入节点
@ -119,76 +51,8 @@
- 二叉搜索树不允许存在重复节点,否则将违反其定义。因此,若待插入节点在树中已存在,则不执行插入,直接返回。
- 为了实现插入节点,我们需要借助节点 `pre` 保存上一轮循环的节点。这样在遍历至 $\text{None}$ 时,我们可以获取到其父节点,从而完成节点插入操作。
=== "Python"
```python title="binary_search_tree.py"
[class]{BinarySearchTree}-[func]{insert}
```
=== "C++"
```cpp title="binary_search_tree.cpp"
[class]{BinarySearchTree}-[func]{insert}
```
=== "Java"
```java title="binary_search_tree.java"
[class]{BinarySearchTree}-[func]{insert}
```
=== "C#"
```csharp title="binary_search_tree.cs"
[class]{BinarySearchTree}-[func]{Insert}
```
=== "Go"
```go title="binary_search_tree.go"
[class]{binarySearchTree}-[func]{insert}
```
=== "Swift"
```swift title="binary_search_tree.swift"
[class]{BinarySearchTree}-[func]{insert}
```
=== "JS"
```javascript title="binary_search_tree.js"
[class]{BinarySearchTree}-[func]{insert}
```
=== "TS"
```typescript title="binary_search_tree.ts"
[class]{BinarySearchTree}-[func]{insert}
```
=== "Dart"
```dart title="binary_search_tree.dart"
[class]{BinarySearchTree}-[func]{insert}
```
=== "Rust"
```rust title="binary_search_tree.rs"
[class]{BinarySearchTree}-[func]{insert}
```
=== "C"
```c title="binary_search_tree.c"
[class]{binarySearchTree}-[func]{insert}
```
=== "Zig"
```zig title="binary_search_tree.zig"
[class]{BinarySearchTree}-[func]{insert}
```src
[file]{binary_search_tree}-[class]{binary_search_tree}-[func]{insert}
```
与查找节点相同,插入节点使用 $O(\log n)$ 时间。
@ -230,76 +94,8 @@
删除节点操作同样使用 $O(\log n)$ 时间,其中查找待删除节点需要 $O(\log n)$ 时间,获取中序遍历后继节点需要 $O(\log n)$ 时间。
=== "Python"
```python title="binary_search_tree.py"
[class]{BinarySearchTree}-[func]{remove}
```
=== "C++"
```cpp title="binary_search_tree.cpp"
[class]{BinarySearchTree}-[func]{remove}
```
=== "Java"
```java title="binary_search_tree.java"
[class]{BinarySearchTree}-[func]{remove}
```
=== "C#"
```csharp title="binary_search_tree.cs"
[class]{BinarySearchTree}-[func]{Remove}
```
=== "Go"
```go title="binary_search_tree.go"
[class]{binarySearchTree}-[func]{remove}
```
=== "Swift"
```swift title="binary_search_tree.swift"
[class]{BinarySearchTree}-[func]{remove}
```
=== "JS"
```javascript title="binary_search_tree.js"
[class]{BinarySearchTree}-[func]{remove}
```
=== "TS"
```typescript title="binary_search_tree.ts"
[class]{BinarySearchTree}-[func]{remove}
```
=== "Dart"
```dart title="binary_search_tree.dart"
[class]{BinarySearchTree}-[func]{remove}
```
=== "Rust"
```rust title="binary_search_tree.rs"
[class]{BinarySearchTree}-[func]{remove}
```
=== "C"
```c title="binary_search_tree.c"
[class]{binarySearchTree}-[func]{removeItem}
```
=== "Zig"
```zig title="binary_search_tree.zig"
[class]{BinarySearchTree}-[func]{remove}
```src
[file]{binary_search_tree}-[class]{binary_search_tree}-[func]{remove}
```
### 中序遍历有序

View file

@ -16,76 +16,8 @@
广度优先遍历通常借助“队列”来实现。队列遵循“先进先出”的规则,而广度优先遍历则遵循“逐层推进”的规则,两者背后的思想是一致的。
=== "Python"
```python title="binary_tree_bfs.py"
[class]{}-[func]{level_order}
```
=== "C++"
```cpp title="binary_tree_bfs.cpp"
[class]{}-[func]{levelOrder}
```
=== "Java"
```java title="binary_tree_bfs.java"
[class]{binary_tree_bfs}-[func]{levelOrder}
```
=== "C#"
```csharp title="binary_tree_bfs.cs"
[class]{binary_tree_bfs}-[func]{LevelOrder}
```
=== "Go"
```go title="binary_tree_bfs.go"
[class]{}-[func]{levelOrder}
```
=== "Swift"
```swift title="binary_tree_bfs.swift"
[class]{}-[func]{levelOrder}
```
=== "JS"
```javascript title="binary_tree_bfs.js"
[class]{}-[func]{levelOrder}
```
=== "TS"
```typescript title="binary_tree_bfs.ts"
[class]{}-[func]{levelOrder}
```
=== "Dart"
```dart title="binary_tree_bfs.dart"
[class]{}-[func]{levelOrder}
```
=== "Rust"
```rust title="binary_tree_bfs.rs"
[class]{}-[func]{level_order}
```
=== "C"
```c title="binary_tree_bfs.c"
[class]{}-[func]{levelOrder}
```
=== "Zig"
```zig title="binary_tree_bfs.zig"
[class]{}-[func]{levelOrder}
```src
[file]{binary_tree_bfs}-[class]{}-[func]{level_order}
```
### 复杂度分析
@ -105,124 +37,8 @@
深度优先搜索通常基于递归实现:
=== "Python"
```python title="binary_tree_dfs.py"
[class]{}-[func]{pre_order}
[class]{}-[func]{in_order}
[class]{}-[func]{post_order}
```
=== "C++"
```cpp title="binary_tree_dfs.cpp"
[class]{}-[func]{preOrder}
[class]{}-[func]{inOrder}
[class]{}-[func]{postOrder}
```
=== "Java"
```java title="binary_tree_dfs.java"
[class]{binary_tree_dfs}-[func]{preOrder}
[class]{binary_tree_dfs}-[func]{inOrder}
[class]{binary_tree_dfs}-[func]{postOrder}
```
=== "C#"
```csharp title="binary_tree_dfs.cs"
[class]{binary_tree_dfs}-[func]{PreOrder}
[class]{binary_tree_dfs}-[func]{InOrder}
[class]{binary_tree_dfs}-[func]{PostOrder}
```
=== "Go"
```go title="binary_tree_dfs.go"
[class]{}-[func]{preOrder}
[class]{}-[func]{inOrder}
[class]{}-[func]{postOrder}
```
=== "Swift"
```swift title="binary_tree_dfs.swift"
[class]{}-[func]{preOrder}
[class]{}-[func]{inOrder}
[class]{}-[func]{postOrder}
```
=== "JS"
```javascript title="binary_tree_dfs.js"
[class]{}-[func]{preOrder}
[class]{}-[func]{inOrder}
[class]{}-[func]{postOrder}
```
=== "TS"
```typescript title="binary_tree_dfs.ts"
[class]{}-[func]{preOrder}
[class]{}-[func]{inOrder}
[class]{}-[func]{postOrder}
```
=== "Dart"
```dart title="binary_tree_dfs.dart"
[class]{}-[func]{preOrder}
[class]{}-[func]{inOrder}
[class]{}-[func]{postOrder}
```
=== "Rust"
```rust title="binary_tree_dfs.rs"
[class]{}-[func]{pre_order}
[class]{}-[func]{in_order}
[class]{}-[func]{post_order}
```
=== "C"
```c title="binary_tree_dfs.c"
[class]{}-[func]{preOrder}
[class]{}-[func]{inOrder}
[class]{}-[func]{postOrder}
```
=== "Zig"
```zig title="binary_tree_dfs.zig"
[class]{}-[func]{preOrder}
[class]{}-[func]{inOrder}
[class]{}-[func]{postOrder}
```src
[file]{binary_tree_dfs}-[class]{}-[func]{post_order}
```
!!! note