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
52 changed files with 409 additions and 10482 deletions

View File

@ -12,77 +12,9 @@
以下函数基于 `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,153 +28,17 @@
下面,我们用 `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,77 +46,9 @@
我们可以在一个循环结构内嵌套另一个循环结构,以 `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,77 +73,9 @@
观察以下代码,我们只需调用函数 `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,77 +113,9 @@
以计算 $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,77 +143,9 @@
按照递推关系进行递归调用,将前两个数字作为终止条件,便可写出递归代码。调用 `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,77 +182,9 @@
因此,**我们可以使用一个显式的栈来模拟调用栈的行为**,从而将递归转化为迭代形式:
=== "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,253 +719,23 @@ $$
需要注意的是,在循环中初始化变量或调用函数而占用的内存,在进入下一循环后就会被释放,因此不会累积占用空间,空间复杂度仍为 $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,151 +743,15 @@ $$
平方阶常见于矩阵和图,元素数量与 $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,77 +759,9 @@ $$
指数阶常见于二叉树。观察下图,高度为 $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,227 +897,23 @@ $$
在以下函数中,尽管操作数量 `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,77 +921,9 @@ $$
平方阶的操作数量相对于输入数据大小 $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,77 +931,9 @@ $$
以冒泡排序为例,外层循环执行 $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,153 +941,17 @@ $$
下图和以下代码模拟了细胞分裂的过程,时间复杂度为 $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,153 +961,17 @@ $$
下图和以下代码模拟了“每轮缩减到一半”的过程,时间复杂度为 $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,77 +989,9 @@ $$
线性对数阶常出现于嵌套循环中,两层循环的时间复杂度分别为 $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,77 +1009,9 @@ $$
阶乘通常使用递归实现。如下图和以下代码所示,第一层分裂出 $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,120 +1026,9 @@ $$
“最差时间复杂度”对应函数渐近上界,使用大 $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}
```
值得说明的是,我们在实际中很少使用最佳时间复杂度,因为通常只有在很小概率下才能达到,可能会带来一定的误导性。**而最差时间复杂度更为实用,因为它给出了一个效率安全值**,让我们可以放心地使用算法。