This commit is contained in:
krahets
2024-03-25 22:43:12 +08:00
parent 22017aa8e5
commit 87af663929
70 changed files with 7428 additions and 32 deletions
@@ -168,6 +168,20 @@ The following function uses a `for` loop to perform a summation of $1 + 2 + \dot
}
```
=== "Kotlin"
```kotlin title="iteration.kt"
/* for 循环 */
fun forLoop(n: Int): Int {
var res = 0
// 循环求和 1, 2, ..., n-1, n
for (i in 1..n) {
res += i
}
return res
}
```
=== "Zig"
```zig title="iteration.zig"
@@ -378,6 +392,22 @@ Below we use a `while` loop to implement the sum $1 + 2 + \dots + n$.
}
```
=== "Kotlin"
```kotlin title="iteration.kt"
/* while 循环 */
fun whileLoop(n: Int): Int {
var res = 0
var i = 1 // 初始化条件变量
// 循环求和 1, 2, ..., n-1, n
while (i <= n) {
res += i
i++ // 更新条件变量
}
return res
}
```
=== "Zig"
```zig title="iteration.zig"
@@ -601,6 +631,24 @@ For example, in the following code, the condition variable $i$ is updated twice
}
```
=== "Kotlin"
```kotlin title="iteration.kt"
/* while 循环(两次更新) */
fun whileLoopII(n: Int): Int {
var res = 0
var i = 1 // 初始化条件变量
// 循环求和 1, 4, 10, ...
while (i <= n) {
res += i
// 更新条件变量
i++
i *= 2
}
return res
}
```
=== "Zig"
```zig title="iteration.zig"
@@ -818,6 +866,23 @@ We can nest one loop structure within another. Below is an example using `for` l
}
```
=== "Kotlin"
```kotlin title="iteration.kt"
/* 双层 for 循环 */
fun nestedForLoop(n: Int): String {
val res = StringBuilder()
// 循环 i = 1, 2, ..., n-1, n
for (i in 1..n) {
// 循环 j = 1, 2, ..., n-1, n
for (j in 1..n) {
res.append(" ($i, $j), ")
}
}
return res.toString()
}
```
=== "Zig"
```zig title="iteration.zig"
@@ -1032,6 +1097,21 @@ Observe the following code, where simply calling the function `recur(n)` can com
}
```
=== "Kotlin"
```kotlin title="recursion.kt"
/* 递归 */
fun recur(n: Int): Int {
// 终止条件
if (n == 1)
return 1
// 递: 递归调用
val res = recur(n - 1)
// 归: 返回结果
return n + res
}
```
=== "Zig"
```zig title="recursion.zig"
@@ -1235,6 +1315,19 @@ For example, in calculating $1 + 2 + \dots + n$, we can make the result variable
}
```
=== "Kotlin"
```kotlin title="recursion.kt"
/* Kotlin tailrec 关键词使函数实现尾递归优化 */
tailrec fun tailRecur(n: Int, res: Int): Int {
// 终止条件
if (n == 0)
return res
// 尾递归调用
return tailRecur(n - 1, res + n)
}
```
=== "Zig"
```zig title="recursion.zig"
@@ -1446,6 +1539,21 @@ Using the recursive relation, and considering the first two numbers as terminati
}
```
=== "Kotlin"
```kotlin title="recursion.kt"
/* 斐波那契数列:递归 */
fun fib(n: Int): Int {
// 终止条件 f(1) = 0, f(2) = 1
if (n == 1 || n == 2)
return n - 1
// 递归调用 f(n) = f(n-1) + f(n-2)
val res = fib(n - 1) + fib(n - 2)
// 返回结果 f(n)
return res
}
```
=== "Zig"
```zig title="recursion.zig"
@@ -1760,6 +1868,28 @@ Therefore, **we can use an explicit stack to simulate the behavior of the call s
}
```
=== "Kotlin"
```kotlin title="recursion.kt"
/* 使用迭代模拟递归 */
fun forLoopRecur(n: Int): Int {
// 使用一个显式的栈来模拟系统调用栈
val stack = Stack<Int>()
var res = 0
// 递: 递归调用
for (i in n downTo 0) {
stack.push(i)
}
// 归: 返回结果
while (stack.isNotEmpty()) {
// 通过“出栈操作”模拟“归”
res += stack.pop()
}
// res = 1+2+3+...+n
return res
}
```
=== "Zig"
```zig title="recursion.zig"
@@ -316,6 +316,12 @@ The relevant code is as follows:
}
```
=== "Kotlin"
```kotlin title=""
```
=== "Zig"
```zig title=""
@@ -462,6 +468,12 @@ Consider the following code, the term "worst-case" in worst-case space complexit
}
```
=== "Kotlin"
```kotlin title=""
```
=== "Zig"
```zig title=""
@@ -482,9 +494,10 @@ Consider the following code, the term "worst-case" in worst-case space complexit
for _ in range(n):
function()
def recur(n: int) -> int:
def recur(n: int):
"""Recursion O(n)"""""
if n == 1: return
if n == 1:
return
return recur(n - 1)
```
@@ -699,6 +712,12 @@ Consider the following code, the term "worst-case" in worst-case space complexit
}
```
=== "Kotlin"
```kotlin title=""
```
=== "Zig"
```zig title=""
@@ -725,7 +744,7 @@ $$
<p align="center"> Figure 2-16 &nbsp; Common Types of Space Complexity </p>
### 1. &nbsp; Constant Order $O(1)$
### 1. &nbsp; Constant Order $O(1)$ {data-toc-label="Constant Order"}
Constant order is common in constants, variables, objects that are independent of the size of input data $n$.
@@ -1031,6 +1050,33 @@ Note that memory occupied by initializing variables or calling functions in a lo
}
```
=== "Kotlin"
```kotlin title="space_complexity.kt"
/* 函数 */
fun function(): Int {
// 执行某些操作
return 0
}
/* 常数阶 */
fun constant(n: Int) {
// 常量、变量、对象占用 O(1) 空间
val a = 0
var b = 0
val nums = Array(10000) { 0 }
val node = ListNode(0)
// 循环中的变量占用 O(1) 空间
for (i in 0..<n) {
val c = 0
}
// 循环中的函数占用 O(1) 空间
for (i in 0..<n) {
function()
}
}
```
=== "Zig"
```zig title="space_complexity.zig"
@@ -1070,7 +1116,7 @@ Note that memory occupied by initializing variables or calling functions in a lo
<div style="height: 549px; width: 100%;"><iframe class="pythontutor-iframe" src="https://pythontutor.com/iframe-embed.html#code=class%20ListNode%3A%0A%20%20%20%20%22%22%22%E9%93%BE%E8%A1%A8%E8%8A%82%E7%82%B9%E7%B1%BB%22%22%22%0A%20%20%20%20def%20__init__%28self,%20val%3A%20int%29%3A%0A%20%20%20%20%20%20%20%20self.val%3A%20int%20%3D%20val%20%20%23%20%E8%8A%82%E7%82%B9%E5%80%BC%0A%20%20%20%20%20%20%20%20self.next%3A%20ListNode%20%7C%20None%20%3D%20None%20%20%23%20%E5%90%8E%E7%BB%A7%E8%8A%82%E7%82%B9%E5%BC%95%E7%94%A8%0A%0Adef%20function%28%29%20-%3E%20int%3A%0A%20%20%20%20%22%22%22%E5%87%BD%E6%95%B0%22%22%22%0A%20%20%20%20%23%20%E6%89%A7%E8%A1%8C%E6%9F%90%E4%BA%9B%E6%93%8D%E4%BD%9C%0A%20%20%20%20return%200%0A%0Adef%20constant%28n%3A%20int%29%3A%0A%20%20%20%20%22%22%22%E5%B8%B8%E6%95%B0%E9%98%B6%22%22%22%0A%20%20%20%20%23%20%E5%B8%B8%E9%87%8F%E3%80%81%E5%8F%98%E9%87%8F%E3%80%81%E5%AF%B9%E8%B1%A1%E5%8D%A0%E7%94%A8%20O%281%29%20%E7%A9%BA%E9%97%B4%0A%20%20%20%20a%20%3D%200%0A%20%20%20%20nums%20%3D%20%5B0%5D%20*%2010%0A%20%20%20%20node%20%3D%20ListNode%280%29%0A%20%20%20%20%23%20%E5%BE%AA%E7%8E%AF%E4%B8%AD%E7%9A%84%E5%8F%98%E9%87%8F%E5%8D%A0%E7%94%A8%20O%281%29%20%E7%A9%BA%E9%97%B4%0A%20%20%20%20for%20_%20in%20range%28n%29%3A%0A%20%20%20%20%20%20%20%20c%20%3D%200%0A%20%20%20%20%23%20%E5%BE%AA%E7%8E%AF%E4%B8%AD%E7%9A%84%E5%87%BD%E6%95%B0%E5%8D%A0%E7%94%A8%20O%281%29%20%E7%A9%BA%E9%97%B4%0A%20%20%20%20for%20_%20in%20range%28n%29%3A%0A%20%20%20%20%20%20%20%20function%28%29%0A%0A%22%22%22Driver%20Code%22%22%22%0Aif%20__name__%20%3D%3D%20%22__main__%22%3A%0A%20%20%20%20n%20%3D%205%0A%20%20%20%20print%28%22%E8%BE%93%E5%85%A5%E6%95%B0%E6%8D%AE%E5%A4%A7%E5%B0%8F%20n%20%3D%22,%20n%29%0A%0A%20%20%20%20%23%20%E5%B8%B8%E6%95%B0%E9%98%B6%0A%20%20%20%20constant%28n%29&codeDivHeight=472&codeDivWidth=350&cumulative=false&curInstr=6&heapPrimitives=nevernest&origin=opt-frontend.js&py=311&rawInputLstJSON=%5B%5D&textReferences=false"> </iframe></div>
<div style="margin-top: 5px;"><a href="https://pythontutor.com/iframe-embed.html#code=class%20ListNode%3A%0A%20%20%20%20%22%22%22%E9%93%BE%E8%A1%A8%E8%8A%82%E7%82%B9%E7%B1%BB%22%22%22%0A%20%20%20%20def%20__init__%28self,%20val%3A%20int%29%3A%0A%20%20%20%20%20%20%20%20self.val%3A%20int%20%3D%20val%20%20%23%20%E8%8A%82%E7%82%B9%E5%80%BC%0A%20%20%20%20%20%20%20%20self.next%3A%20ListNode%20%7C%20None%20%3D%20None%20%20%23%20%E5%90%8E%E7%BB%A7%E8%8A%82%E7%82%B9%E5%BC%95%E7%94%A8%0A%0Adef%20function%28%29%20-%3E%20int%3A%0A%20%20%20%20%22%22%22%E5%87%BD%E6%95%B0%22%22%22%0A%20%20%20%20%23%20%E6%89%A7%E8%A1%8C%E6%9F%90%E4%BA%9B%E6%93%8D%E4%BD%9C%0A%20%20%20%20return%200%0A%0Adef%20constant%28n%3A%20int%29%3A%0A%20%20%20%20%22%22%22%E5%B8%B8%E6%95%B0%E9%98%B6%22%22%22%0A%20%20%20%20%23%20%E5%B8%B8%E9%87%8F%E3%80%81%E5%8F%98%E9%87%8F%E3%80%81%E5%AF%B9%E8%B1%A1%E5%8D%A0%E7%94%A8%20O%281%29%20%E7%A9%BA%E9%97%B4%0A%20%20%20%20a%20%3D%200%0A%20%20%20%20nums%20%3D%20%5B0%5D%20*%2010%0A%20%20%20%20node%20%3D%20ListNode%280%29%0A%20%20%20%20%23%20%E5%BE%AA%E7%8E%AF%E4%B8%AD%E7%9A%84%E5%8F%98%E9%87%8F%E5%8D%A0%E7%94%A8%20O%281%29%20%E7%A9%BA%E9%97%B4%0A%20%20%20%20for%20_%20in%20range%28n%29%3A%0A%20%20%20%20%20%20%20%20c%20%3D%200%0A%20%20%20%20%23%20%E5%BE%AA%E7%8E%AF%E4%B8%AD%E7%9A%84%E5%87%BD%E6%95%B0%E5%8D%A0%E7%94%A8%20O%281%29%20%E7%A9%BA%E9%97%B4%0A%20%20%20%20for%20_%20in%20range%28n%29%3A%0A%20%20%20%20%20%20%20%20function%28%29%0A%0A%22%22%22Driver%20Code%22%22%22%0Aif%20__name__%20%3D%3D%20%22__main__%22%3A%0A%20%20%20%20n%20%3D%205%0A%20%20%20%20print%28%22%E8%BE%93%E5%85%A5%E6%95%B0%E6%8D%AE%E5%A4%A7%E5%B0%8F%20n%20%3D%22,%20n%29%0A%0A%20%20%20%20%23%20%E5%B8%B8%E6%95%B0%E9%98%B6%0A%20%20%20%20constant%28n%29&codeDivHeight=800&codeDivWidth=600&cumulative=false&curInstr=6&heapPrimitives=nevernest&origin=opt-frontend.js&py=311&rawInputLstJSON=%5B%5D&textReferences=false" target="_blank" rel="noopener noreferrer">Full Screen ></a></div>
### 2. &nbsp; Linear Order $O(n)$
### 2. &nbsp; Linear Order $O(n)$ {data-toc-label="Linear Order"}
Linear order is common in arrays, linked lists, stacks, queues, etc., where the number of elements is proportional to $n$:
@@ -1307,6 +1353,26 @@ Linear order is common in arrays, linked lists, stacks, queues, etc., where the
}
```
=== "Kotlin"
```kotlin title="space_complexity.kt"
/* 线性阶 */
fun linear(n: Int) {
// 长度为 n 的数组占用 O(n) 空间
val nums = Array(n) { 0 }
// 长度为 n 的列表占用 O(n) 空间
val nodes = mutableListOf<ListNode>()
for (i in 0..<n) {
nodes.add(ListNode(i))
}
// 长度为 n 的哈希表占用 O(n) 空间
val map = mutableMapOf<Int, String>()
for (i in 0..<n) {
map[i] = i.toString()
}
}
```
=== "Zig"
```zig title="space_complexity.zig"
@@ -1471,6 +1537,18 @@ As shown below, this function's recursive depth is $n$, meaning there are $n$ in
}
```
=== "Kotlin"
```kotlin title="space_complexity.kt"
/* 线性阶(递归实现) */
fun linearRecur(n: Int) {
println("递归 n = $n")
if (n == 1)
return
linearRecur(n - 1)
}
```
=== "Zig"
```zig title="space_complexity.zig"
@@ -1491,7 +1569,7 @@ As shown below, this function's recursive depth is $n$, meaning there are $n$ in
<p align="center"> Figure 2-17 &nbsp; Recursive Function Generating Linear Order Space Complexity </p>
### 3. &nbsp; Quadratic Order $O(n^2)$
### 3. &nbsp; Quadratic Order $O(n^2)$ {data-toc-label="Quadratic Order"}
Quadratic order is common in matrices and graphs, where the number of elements is quadratic to $n$:
@@ -1686,6 +1764,25 @@ Quadratic order is common in matrices and graphs, where the number of elements i
}
```
=== "Kotlin"
```kotlin title="space_complexity.kt"
/* 平方阶 */
fun quadratic(n: Int) {
// 矩阵占用 O(n^2) 空间
val numMatrix: Array<Array<Int>?> = arrayOfNulls(n)
// 二维列表占用 O(n^2) 空间
val numList: MutableList<MutableList<Int>> = arrayListOf()
for (i in 0..<n) {
val tmp = mutableListOf<Int>()
for (j in 0..<n) {
tmp.add(0)
}
numList.add(tmp)
}
}
```
=== "Zig"
```zig title="space_complexity.zig"
@@ -1861,6 +1958,20 @@ As shown below, the recursive depth of this function is $n$, and in each recursi
}
```
=== "Kotlin"
```kotlin title="space_complexity.kt"
/* 平方阶(递归实现) */
tailrec fun quadraticRecur(n: Int): Int {
if (n <= 0)
return 0
// 数组 nums 长度为 n, n-1, ..., 2, 1
val nums = Array(n) { 0 }
println("递归 n = $n 中的 nums 长度 = ${nums.size}")
return quadraticRecur(n - 1)
}
```
=== "Zig"
```zig title="space_complexity.zig"
@@ -1882,7 +1993,7 @@ As shown below, the recursive depth of this function is $n$, and in each recursi
<p align="center"> Figure 2-18 &nbsp; Recursive Function Generating Quadratic Order Space Complexity </p>
### 4. &nbsp; Exponential Order $O(2^n)$
### 4. &nbsp; Exponential Order $O(2^n)$ {data-toc-label="Exponential Order"}
Exponential order is common in binary trees. Observe the below image, a "full binary tree" with $n$ levels has $2^n - 1$ nodes, occupying $O(2^n)$ space:
@@ -2039,6 +2150,20 @@ Exponential order is common in binary trees. Observe the below image, a "full bi
}
```
=== "Kotlin"
```kotlin title="space_complexity.kt"
/* 指数阶(建立满二叉树) */
fun buildTree(n: Int): TreeNode? {
if (n == 0)
return null
val root = TreeNode(0)
root.left = buildTree(n - 1)
root.right = buildTree(n - 1)
return root
}
```
=== "Zig"
```zig title="space_complexity.zig"
@@ -2062,7 +2187,7 @@ Exponential order is common in binary trees. Observe the below image, a "full bi
<p align="center"> Figure 2-19 &nbsp; Full Binary Tree Generating Exponential Order Space Complexity </p>
### 5. &nbsp; Logarithmic Order $O(\log n)$
### 5. &nbsp; Logarithmic Order $O(\log n)$ {data-toc-label="Logarithmic Order"}
Logarithmic order is common in divide-and-conquer algorithms. For example, in merge sort, an array of length $n$ is recursively divided in half each round, forming a recursion tree of height $\log n$, using $O(\log n)$ stack frame space.
@@ -175,6 +175,12 @@ For example, consider the following code with an input size of $n$:
}
```
=== "Kotlin"
```kotlin title=""
```
=== "Zig"
```zig title=""
@@ -433,6 +439,12 @@ Let's understand this concept of "time growth trend" with an example. Assume the
}
```
=== "Kotlin"
```kotlin title=""
```
=== "Zig"
```zig title=""
@@ -629,6 +641,12 @@ Consider a function with an input size of $n$:
}
```
=== "Kotlin"
```kotlin title=""
```
=== "Zig"
```zig title=""
@@ -886,6 +904,12 @@ Given a function, we can use these techniques to count operations:
}
```
=== "Kotlin"
```kotlin title=""
```
=== "Zig"
```zig title=""
@@ -952,7 +976,7 @@ $$
<p align="center"> Figure 2-9 &nbsp; Common Types of Time Complexity </p>
### 1. &nbsp; Constant Order $O(1)$
### 1. &nbsp; Constant Order $O(1)$ {data-toc-label="Constant Order"}
Constant order means the number of operations is independent of the input data size $n$. In the following function, although the number of operations `size` might be large, the time complexity remains $O(1)$ as it's unrelated to $n$:
@@ -1103,6 +1127,19 @@ Constant order means the number of operations is independent of the input data s
}
```
=== "Kotlin"
```kotlin title="time_complexity.kt"
/* 常数阶 */
fun constant(n: Int): Int {
var count = 0
val size = 10_0000
for (i in 0..<size)
count++
return count
}
```
=== "Zig"
```zig title="time_complexity.zig"
@@ -1124,7 +1161,7 @@ Constant order means the number of operations is independent of the input data s
<div style="height: 459px; width: 100%;"><iframe class="pythontutor-iframe" src="https://pythontutor.com/iframe-embed.html#code=def%20constant%28n%3A%20int%29%20-%3E%20int%3A%0A%20%20%20%20%22%22%22%E5%B8%B8%E6%95%B0%E9%98%B6%22%22%22%0A%20%20%20%20count%20%3D%200%0A%20%20%20%20size%20%3D%2010%0A%20%20%20%20for%20_%20in%20range%28size%29%3A%0A%20%20%20%20%20%20%20%20count%20%2B%3D%201%0A%20%20%20%20return%20count%0A%0A%22%22%22Driver%20Code%22%22%22%0Aif%20__name__%20%3D%3D%20%22__main__%22%3A%0A%20%20%20%20n%20%3D%208%0A%20%20%20%20print%28%22%E8%BE%93%E5%85%A5%E6%95%B0%E6%8D%AE%E5%A4%A7%E5%B0%8F%20n%20%3D%22,%20n%29%0A%0A%20%20%20%20count%20%3D%20constant%28n%29%0A%20%20%20%20print%28%22%E5%B8%B8%E6%95%B0%E9%98%B6%E7%9A%84%E6%93%8D%E4%BD%9C%E6%95%B0%E9%87%8F%20%3D%22,%20count%29&codeDivHeight=472&codeDivWidth=350&cumulative=false&curInstr=3&heapPrimitives=nevernest&origin=opt-frontend.js&py=311&rawInputLstJSON=%5B%5D&textReferences=false"> </iframe></div>
<div style="margin-top: 5px;"><a href="https://pythontutor.com/iframe-embed.html#code=def%20constant%28n%3A%20int%29%20-%3E%20int%3A%0A%20%20%20%20%22%22%22%E5%B8%B8%E6%95%B0%E9%98%B6%22%22%22%0A%20%20%20%20count%20%3D%200%0A%20%20%20%20size%20%3D%2010%0A%20%20%20%20for%20_%20in%20range%28size%29%3A%0A%20%20%20%20%20%20%20%20count%20%2B%3D%201%0A%20%20%20%20return%20count%0A%0A%22%22%22Driver%20Code%22%22%22%0Aif%20__name__%20%3D%3D%20%22__main__%22%3A%0A%20%20%20%20n%20%3D%208%0A%20%20%20%20print%28%22%E8%BE%93%E5%85%A5%E6%95%B0%E6%8D%AE%E5%A4%A7%E5%B0%8F%20n%20%3D%22,%20n%29%0A%0A%20%20%20%20count%20%3D%20constant%28n%29%0A%20%20%20%20print%28%22%E5%B8%B8%E6%95%B0%E9%98%B6%E7%9A%84%E6%93%8D%E4%BD%9C%E6%95%B0%E9%87%8F%20%3D%22,%20count%29&codeDivHeight=800&codeDivWidth=600&cumulative=false&curInstr=3&heapPrimitives=nevernest&origin=opt-frontend.js&py=311&rawInputLstJSON=%5B%5D&textReferences=false" target="_blank" rel="noopener noreferrer">Full Screen ></a></div>
### 2. &nbsp; Linear Order $O(n)$
### 2. &nbsp; Linear Order $O(n)$ {data-toc-label="Linear Order"}
Linear order indicates the number of operations grows linearly with the input data size $n$. Linear order commonly appears in single-loop structures:
@@ -1262,6 +1299,19 @@ Linear order indicates the number of operations grows linearly with the input da
}
```
=== "Kotlin"
```kotlin title="time_complexity.kt"
/* 线性阶 */
fun linear(n: Int): Int {
var count = 0
// 循环次数与数组长度成正比
for (i in 0..<n)
count++
return count
}
```
=== "Zig"
```zig title="time_complexity.zig"
@@ -1435,6 +1485,20 @@ Operations like array traversal and linked list traversal have a time complexity
}
```
=== "Kotlin"
```kotlin title="time_complexity.kt"
/* 线性阶(遍历数组) */
fun arrayTraversal(nums: IntArray): Int {
var count = 0
// 循环次数与数组长度成正比
for (num in nums) {
count++
}
return count
}
```
=== "Zig"
```zig title="time_complexity.zig"
@@ -1456,7 +1520,7 @@ Operations like array traversal and linked list traversal have a time complexity
It's important to note that **the input data size $n$ should be determined based on the type of input data**. For example, in the first example, $n$ represents the input data size, while in the second example, the length of the array $n$ is the data size.
### 3. &nbsp; Quadratic Order $O(n^2)$
### 3. &nbsp; Quadratic Order $O(n^2)$ {data-toc-label="Quadratic Order"}
Quadratic order means the number of operations grows quadratically with the input data size $n$. Quadratic order typically appears in nested loops, where both the outer and inner loops have a time complexity of $O(n)$, resulting in an overall complexity of $O(n^2)$:
@@ -1633,6 +1697,22 @@ Quadratic order means the number of operations grows quadratically with the inpu
}
```
=== "Kotlin"
```kotlin title="time_complexity.kt"
/* 平方阶 */
fun quadratic(n: Int): Int {
var count = 0
// 循环次数与数据大小 n 成平方关系
for (i in 0..<n) {
for (j in 0..<n) {
count++
}
}
return count
}
```
=== "Zig"
```zig title="time_complexity.zig"
@@ -1912,6 +1992,27 @@ For instance, in bubble sort, the outer loop runs $n - 1$ times, and the inner l
}
```
=== "Kotlin"
```kotlin title="time_complexity.kt"
/* 平方阶(冒泡排序) */
fun bubbleSort(nums: IntArray): Int {
var count = 0
// 外循环:未排序区间为 [0, i]
for (i in nums.size - 1 downTo 1) {
// 内循环:将未排序区间 [0, i] 中的最大元素交换至该区间的最右端
for (j in 0..<i) {
if (nums[j] > nums[j + 1]) {
// 交换 nums[j] 与 nums[j + 1]
nums[j] = nums[j + 1].also { nums[j + 1] = nums[j] }
count += 3 // 元素交换包含 3 个单元操作
}
}
}
return count
}
```
=== "Zig"
```zig title="time_complexity.zig"
@@ -1942,7 +2043,7 @@ For instance, in bubble sort, the outer loop runs $n - 1$ times, and the inner l
<div style="height: 549px; width: 100%;"><iframe class="pythontutor-iframe" src="https://pythontutor.com/iframe-embed.html#code=def%20bubble_sort%28nums%3A%20list%5Bint%5D%29%20-%3E%20int%3A%0A%20%20%20%20%22%22%22%E5%B9%B3%E6%96%B9%E9%98%B6%EF%BC%88%E5%86%92%E6%B3%A1%E6%8E%92%E5%BA%8F%EF%BC%89%22%22%22%0A%20%20%20%20count%20%3D%200%20%20%23%20%E8%AE%A1%E6%95%B0%E5%99%A8%0A%20%20%20%20%23%20%E5%A4%96%E5%BE%AA%E7%8E%AF%EF%BC%9A%E6%9C%AA%E6%8E%92%E5%BA%8F%E5%8C%BA%E9%97%B4%E4%B8%BA%20%5B0,%20i%5D%0A%20%20%20%20for%20i%20in%20range%28len%28nums%29%20-%201,%200,%20-1%29%3A%0A%20%20%20%20%20%20%20%20%23%20%E5%86%85%E5%BE%AA%E7%8E%AF%EF%BC%9A%E5%B0%86%E6%9C%AA%E6%8E%92%E5%BA%8F%E5%8C%BA%E9%97%B4%20%5B0,%20i%5D%20%E4%B8%AD%E7%9A%84%E6%9C%80%E5%A4%A7%E5%85%83%E7%B4%A0%E4%BA%A4%E6%8D%A2%E8%87%B3%E8%AF%A5%E5%8C%BA%E9%97%B4%E7%9A%84%E6%9C%80%E5%8F%B3%E7%AB%AF%0A%20%20%20%20%20%20%20%20for%20j%20in%20range%28i%29%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20nums%5Bj%5D%20%3E%20nums%5Bj%20%2B%201%5D%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%23%20%E4%BA%A4%E6%8D%A2%20nums%5Bj%5D%20%E4%B8%8E%20nums%5Bj%20%2B%201%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20tmp%20%3D%20nums%5Bj%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20nums%5Bj%5D%20%3D%20nums%5Bj%20%2B%201%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20nums%5Bj%20%2B%201%5D%20%3D%20tmp%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20count%20%2B%3D%203%20%20%23%20%E5%85%83%E7%B4%A0%E4%BA%A4%E6%8D%A2%E5%8C%85%E5%90%AB%203%20%E4%B8%AA%E5%8D%95%E5%85%83%E6%93%8D%E4%BD%9C%0A%20%20%20%20return%20count%0A%0A%22%22%22Driver%20Code%22%22%22%0Aif%20__name__%20%3D%3D%20%22__main__%22%3A%0A%20%20%20%20n%20%3D%208%0A%20%20%20%20print%28%22%E8%BE%93%E5%85%A5%E6%95%B0%E6%8D%AE%E5%A4%A7%E5%B0%8F%20n%20%3D%22,%20n%29%0A%0A%20%20%20%20nums%20%3D%20%5Bi%20for%20i%20in%20range%28n,%200,%20-1%29%5D%20%20%23%20%5Bn,%20n-1,%20...,%202,%201%5D%0A%20%20%20%20count%20%3D%20bubble_sort%28nums%29%0A%20%20%20%20print%28%22%E5%B9%B3%E6%96%B9%E9%98%B6%EF%BC%88%E5%86%92%E6%B3%A1%E6%8E%92%E5%BA%8F%EF%BC%89%E7%9A%84%E6%93%8D%E4%BD%9C%E6%95%B0%E9%87%8F%20%3D%22,%20count%29&codeDivHeight=472&codeDivWidth=350&cumulative=false&curInstr=3&heapPrimitives=nevernest&origin=opt-frontend.js&py=311&rawInputLstJSON=%5B%5D&textReferences=false"> </iframe></div>
<div style="margin-top: 5px;"><a href="https://pythontutor.com/iframe-embed.html#code=def%20bubble_sort%28nums%3A%20list%5Bint%5D%29%20-%3E%20int%3A%0A%20%20%20%20%22%22%22%E5%B9%B3%E6%96%B9%E9%98%B6%EF%BC%88%E5%86%92%E6%B3%A1%E6%8E%92%E5%BA%8F%EF%BC%89%22%22%22%0A%20%20%20%20count%20%3D%200%20%20%23%20%E8%AE%A1%E6%95%B0%E5%99%A8%0A%20%20%20%20%23%20%E5%A4%96%E5%BE%AA%E7%8E%AF%EF%BC%9A%E6%9C%AA%E6%8E%92%E5%BA%8F%E5%8C%BA%E9%97%B4%E4%B8%BA%20%5B0,%20i%5D%0A%20%20%20%20for%20i%20in%20range%28len%28nums%29%20-%201,%200,%20-1%29%3A%0A%20%20%20%20%20%20%20%20%23%20%E5%86%85%E5%BE%AA%E7%8E%AF%EF%BC%9A%E5%B0%86%E6%9C%AA%E6%8E%92%E5%BA%8F%E5%8C%BA%E9%97%B4%20%5B0,%20i%5D%20%E4%B8%AD%E7%9A%84%E6%9C%80%E5%A4%A7%E5%85%83%E7%B4%A0%E4%BA%A4%E6%8D%A2%E8%87%B3%E8%AF%A5%E5%8C%BA%E9%97%B4%E7%9A%84%E6%9C%80%E5%8F%B3%E7%AB%AF%0A%20%20%20%20%20%20%20%20for%20j%20in%20range%28i%29%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20nums%5Bj%5D%20%3E%20nums%5Bj%20%2B%201%5D%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%23%20%E4%BA%A4%E6%8D%A2%20nums%5Bj%5D%20%E4%B8%8E%20nums%5Bj%20%2B%201%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20tmp%20%3D%20nums%5Bj%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20nums%5Bj%5D%20%3D%20nums%5Bj%20%2B%201%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20nums%5Bj%20%2B%201%5D%20%3D%20tmp%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20count%20%2B%3D%203%20%20%23%20%E5%85%83%E7%B4%A0%E4%BA%A4%E6%8D%A2%E5%8C%85%E5%90%AB%203%20%E4%B8%AA%E5%8D%95%E5%85%83%E6%93%8D%E4%BD%9C%0A%20%20%20%20return%20count%0A%0A%22%22%22Driver%20Code%22%22%22%0Aif%20__name__%20%3D%3D%20%22__main__%22%3A%0A%20%20%20%20n%20%3D%208%0A%20%20%20%20print%28%22%E8%BE%93%E5%85%A5%E6%95%B0%E6%8D%AE%E5%A4%A7%E5%B0%8F%20n%20%3D%22,%20n%29%0A%0A%20%20%20%20nums%20%3D%20%5Bi%20for%20i%20in%20range%28n,%200,%20-1%29%5D%20%20%23%20%5Bn,%20n-1,%20...,%202,%201%5D%0A%20%20%20%20count%20%3D%20bubble_sort%28nums%29%0A%20%20%20%20print%28%22%E5%B9%B3%E6%96%B9%E9%98%B6%EF%BC%88%E5%86%92%E6%B3%A1%E6%8E%92%E5%BA%8F%EF%BC%89%E7%9A%84%E6%93%8D%E4%BD%9C%E6%95%B0%E9%87%8F%20%3D%22,%20count%29&codeDivHeight=800&codeDivWidth=600&cumulative=false&curInstr=3&heapPrimitives=nevernest&origin=opt-frontend.js&py=311&rawInputLstJSON=%5B%5D&textReferences=false" target="_blank" rel="noopener noreferrer">Full Screen ></a></div>
### 4. &nbsp; Exponential Order $O(2^n)$
### 4. &nbsp; Exponential Order $O(2^n)$ {data-toc-label="Exponential Order"}
Biological "cell division" is a classic example of exponential order growth: starting with one cell, it becomes two after one division, four after two divisions, and so on, resulting in $2^n$ cells after $n$ divisions.
@@ -2149,6 +2250,25 @@ The following image and code simulate the cell division process, with a time com
}
```
=== "Kotlin"
```kotlin title="time_complexity.kt"
/* 指数阶(循环实现) */
fun exponential(n: Int): Int {
var count = 0
// 细胞每轮一分为二,形成数列 1, 2, 4, 8, ..., 2^(n-1)
var base = 1
for (i in 0..<n) {
for (j in 0..<base) {
count++
}
base *= 2
}
// count = 1 + 2 + 4 + 8 + .. + 2^(n-1) = 2^n - 1
return count
}
```
=== "Zig"
```zig title="time_complexity.zig"
@@ -2300,6 +2420,18 @@ In practice, exponential order often appears in recursive functions. For example
}
```
=== "Kotlin"
```kotlin title="time_complexity.kt"
/* 指数阶(递归实现) */
fun expRecur(n: Int): Int {
if (n == 1) {
return 1
}
return expRecur(n - 1) + expRecur(n - 1) + 1
}
```
=== "Zig"
```zig title="time_complexity.zig"
@@ -2317,7 +2449,7 @@ In practice, exponential order often appears in recursive functions. For example
Exponential order growth is extremely rapid and is commonly seen in exhaustive search methods (brute force, backtracking, etc.). For large-scale problems, exponential order is unacceptable, often requiring dynamic programming or greedy algorithms as solutions.
### 5. &nbsp; Logarithmic Order $O(\log n)$
### 5. &nbsp; Logarithmic Order $O(\log n)$ {data-toc-label="Logarithmic Order"}
In contrast to exponential order, logarithmic order reflects situations where "the size is halved each round." Given an input data size $n$, since the size is halved each round, the number of iterations is $\log_2 n$, the inverse function of $2^n$.
@@ -2476,6 +2608,21 @@ The following image and code simulate the "halving each round" process, with a t
}
```
=== "Kotlin"
```kotlin title="time_complexity.kt"
/* 对数阶(循环实现) */
fun logarithmic(n: Int): Int {
var n1 = n
var count = 0
while (n1 > 1) {
n1 /= 2
count++
}
return count
}
```
=== "Zig"
```zig title="time_complexity.zig"
@@ -2622,6 +2769,17 @@ Like exponential order, logarithmic order also frequently appears in recursive f
}
```
=== "Kotlin"
```kotlin title="time_complexity.kt"
/* 对数阶(递归实现) */
fun logRecur(n: Int): Int {
if (n <= 1)
return 0
return logRecur(n / 2) + 1
}
```
=== "Zig"
```zig title="time_complexity.zig"
@@ -2649,7 +2807,7 @@ Logarithmic order is typical in algorithms based on the divide-and-conquer strat
This means the base $m$ can be changed without affecting the complexity. Therefore, we often omit the base $m$ and simply denote logarithmic order as $O(\log n)$.
### 6. &nbsp; Linear-Logarithmic Order $O(n \log n)$
### 6. &nbsp; Linear-Logarithmic Order $O(n \log n)$ {data-toc-label="Linear-Logarithmic Order"}
Linear-logarithmic order often appears in nested loops, with the complexities of the two loops being $O(\log n)$ and $O(n)$ respectively. The related code is as follows:
@@ -2815,6 +2973,21 @@ Linear-logarithmic order often appears in nested loops, with the complexities of
}
```
=== "Kotlin"
```kotlin title="time_complexity.kt"
/* 线性对数阶 */
fun linearLogRecur(n: Int): Int {
if (n <= 1)
return 1
var count = linearLogRecur(n / 2) + linearLogRecur(n / 2)
for (i in 0..<n.toInt()) {
count++
}
return count
}
```
=== "Zig"
```zig title="time_complexity.zig"
@@ -2843,7 +3016,7 @@ The image below demonstrates how linear-logarithmic order is generated. Each lev
Mainstream sorting algorithms typically have a time complexity of $O(n \log n)$, such as quicksort, mergesort, and heapsort.
### 7. &nbsp; Factorial Order $O(n!)$
### 7. &nbsp; Factorial Order $O(n!)$ {data-toc-label="Factorial Order"}
Factorial order corresponds to the mathematical problem of "full permutation." Given $n$ distinct elements, the total number of possible permutations is:
@@ -3025,6 +3198,22 @@ Factorials are typically implemented using recursion. As shown in the image and
}
```
=== "Kotlin"
```kotlin title="time_complexity.kt"
/* 阶乘阶(递归实现) */
fun factorialRecur(n: Int): Int {
if (n == 0)
return 1
var count = 0
// 从 1 个分裂出 n 个
for (i in 0..<n) {
count += factorialRecur(n - 1)
}
return count
}
```
=== "Zig"
```zig title="time_complexity.zig"
@@ -3381,6 +3570,39 @@ The "worst-case time complexity" corresponds to the asymptotic upper bound, deno
}
```
=== "Kotlin"
```kotlin title="worst_best_time_complexity.kt"
/* 生成一个数组,元素为 { 1, 2, ..., n },顺序被打乱 */
fun randomNumbers(n: Int): Array<Int?> {
val nums = IntArray(n)
// 生成数组 nums = { 1, 2, 3, ..., n }
for (i in 0..<n) {
nums[i] = i + 1
}
// 随机打乱数组元素
val mutableList = nums.toMutableList()
mutableList.shuffle()
// Integer[] -> int[]
val res = arrayOfNulls<Int>(n)
for (i in 0..<n) {
res[i] = mutableList[i]
}
return res
}
/* 查找数组 nums 中数字 1 所在索引 */
fun findOne(nums: Array<Int?>): Int {
for (i in nums.indices) {
// 当元素 1 在数组头部时,达到最佳时间复杂度 O(1)
// 当元素 1 在数组尾部时,达到最差时间复杂度 O(n)
if (nums[i] == 1)
return i
}
return -1
}
```
=== "Zig"
```zig title="worst_best_time_complexity.zig"