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

View File

@@ -168,6 +168,20 @@ comments: true
}
```
=== "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 @@ comments: true
}
```
=== "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 @@ comments: true
}
```
=== "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 @@ comments: true
}
```
=== "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 @@ comments: true
}
```
=== "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 @@ comments: true
}
```
=== "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 @@ comments: true
}
```
=== "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 @@ comments: true
}
```
=== "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"

View File

@@ -315,6 +315,12 @@ comments: true
}
```
=== "Kotlin"
```kotlin title=""
```
=== "Zig"
```zig title=""
@@ -461,6 +467,12 @@ comments: true
}
```
=== "Kotlin"
```kotlin title=""
```
=== "Zig"
```zig title=""
@@ -481,9 +493,10 @@ comments: true
for _ in range(n):
function()
def recur(n: int) -> int:
def recur(n: int):
"""递归的空间复杂度为 O(n)"""
if n == 1: return
if n == 1:
return
return recur(n - 1)
```
@@ -698,6 +711,12 @@ comments: true
}
```
=== "Kotlin"
```kotlin title=""
```
=== "Zig"
```zig title=""
@@ -724,7 +743,7 @@ $$
<p align="center"> 图 2-16 &nbsp; 常见的空间复杂度类型 </p>
### 1. &nbsp; 常数阶 $O(1)$
### 1. &nbsp; 常数阶 $O(1)$ {data-toc-label="常数阶"}
常数阶常见于数量与输入数据大小 $n$ 无关的常量、变量、对象。
@@ -1030,6 +1049,33 @@ $$
}
```
=== "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"
@@ -1069,7 +1115,7 @@ $$
<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">全屏观看 ></a></div>
### 2. &nbsp; 线性阶 $O(n)$
### 2. &nbsp; 线性阶 $O(n)$ {data-toc-label="线性阶"}
线性阶常见于元素数量与 $n$ 成正比的数组、链表、栈、队列等:
@@ -1306,6 +1352,26 @@ $$
}
```
=== "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"
@@ -1470,6 +1536,18 @@ $$
}
```
=== "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"
@@ -1490,7 +1568,7 @@ $$
<p align="center"> 图 2-17 &nbsp; 递归函数产生的线性阶空间复杂度 </p>
### 3. &nbsp; 平方阶 $O(n^2)$
### 3. &nbsp; 平方阶 $O(n^2)$ {data-toc-label="平方阶"}
平方阶常见于矩阵和图,元素数量与 $n$ 成平方关系:
@@ -1685,6 +1763,25 @@ $$
}
```
=== "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"
@@ -1860,6 +1957,20 @@ $$
}
```
=== "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"
@@ -1881,7 +1992,7 @@ $$
<p align="center"> 图 2-18 &nbsp; 递归函数产生的平方阶空间复杂度 </p>
### 4. &nbsp; 指数阶 $O(2^n)$
### 4. &nbsp; 指数阶 $O(2^n)$ {data-toc-label="指数阶"}
指数阶常见于二叉树。观察图 2-19 ,层数为 $n$ 的“满二叉树”的节点数量为 $2^n - 1$ ,占用 $O(2^n)$ 空间:
@@ -2038,6 +2149,20 @@ $$
}
```
=== "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"
@@ -2061,7 +2186,7 @@ $$
<p align="center"> 图 2-19 &nbsp; 满二叉树产生的指数阶空间复杂度 </p>
### 5. &nbsp; 对数阶 $O(\log n)$
### 5. &nbsp; 对数阶 $O(\log n)$ {data-toc-label="对数阶"}
对数阶常见于分治算法。例如归并排序,输入长度为 $n$ 的数组,每轮递归将数组从中点处划分为两半,形成高度为 $\log n$ 的递归树,使用 $O(\log n)$ 栈帧空间。

View File

@@ -175,6 +175,12 @@ comments: true
}
```
=== "Kotlin"
```kotlin title=""
```
=== "Zig"
```zig title=""
@@ -433,6 +439,12 @@ $$
}
```
=== "Kotlin"
```kotlin title=""
```
=== "Zig"
```zig title=""
@@ -629,6 +641,12 @@ $$
}
```
=== "Kotlin"
```kotlin title=""
```
=== "Zig"
```zig title=""
@@ -888,6 +906,12 @@ $T(n)$ 是一次函数,说明其运行时间的增长趋势是线性的,因
}
```
=== "Kotlin"
```kotlin title=""
```
=== "Zig"
```zig title=""
@@ -954,7 +978,7 @@ $$
<p align="center"> 图 2-9 &nbsp; 常见的时间复杂度类型 </p>
### 1. &nbsp; 常数阶 $O(1)$
### 1. &nbsp; 常数阶 $O(1)$ {data-toc-label="常数阶"}
常数阶的操作数量与输入数据大小 $n$ 无关,即不随着 $n$ 的变化而变化。
@@ -1107,6 +1131,19 @@ $$
}
```
=== "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"
@@ -1128,7 +1165,7 @@ $$
<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">全屏观看 ></a></div>
### 2. &nbsp; 线性阶 $O(n)$
### 2. &nbsp; 线性阶 $O(n)$ {data-toc-label="线性阶"}
线性阶的操作数量相对于输入数据大小 $n$ 以线性级别增长。线性阶通常出现在单层循环中:
@@ -1266,6 +1303,19 @@ $$
}
```
=== "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"
@@ -1439,6 +1489,20 @@ $$
}
```
=== "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"
@@ -1460,7 +1524,7 @@ $$
值得注意的是,**输入数据大小 $n$ 需根据输入数据的类型来具体确定**。比如在第一个示例中,变量 $n$ 为输入数据大小;在第二个示例中,数组长度 $n$ 为数据大小。
### 3. &nbsp; 平方阶 $O(n^2)$
### 3. &nbsp; 平方阶 $O(n^2)$ {data-toc-label="平方阶"}
平方阶的操作数量相对于输入数据大小 $n$ 以平方级别增长。平方阶通常出现在嵌套循环中,外层循环和内层循环的时间复杂度都为 $O(n)$ ,因此总体的时间复杂度为 $O(n^2)$
@@ -1637,6 +1701,22 @@ $$
}
```
=== "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"
@@ -1916,6 +1996,27 @@ $$
}
```
=== "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"
@@ -1946,7 +2047,7 @@ $$
<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">全屏观看 ></a></div>
### 4. &nbsp; 指数阶 $O(2^n)$
### 4. &nbsp; 指数阶 $O(2^n)$ {data-toc-label="指数阶"}
生物学的“细胞分裂”是指数阶增长的典型例子:初始状态为 $1$ 个细胞,分裂一轮后变为 $2$ 个,分裂两轮后变为 $4$ 个,以此类推,分裂 $n$ 轮后有 $2^n$ 个细胞。
@@ -2153,6 +2254,25 @@ $$
}
```
=== "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"
@@ -2304,6 +2424,18 @@ $$
}
```
=== "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"
@@ -2321,7 +2453,7 @@ $$
指数阶增长非常迅速,在穷举法(暴力搜索、回溯等)中比较常见。对于数据规模较大的问题,指数阶是不可接受的,通常需要使用动态规划或贪心算法等来解决。
### 5. &nbsp; 对数阶 $O(\log n)$
### 5. &nbsp; 对数阶 $O(\log n)$ {data-toc-label="对数阶"}
与指数阶相反,对数阶反映了“每轮缩减到一半”的情况。设输入数据大小为 $n$ ,由于每轮缩减到一半,因此循环次数是 $\log_2 n$ ,即 $2^n$ 的反函数。
@@ -2480,6 +2612,21 @@ $$
}
```
=== "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"
@@ -2626,6 +2773,17 @@ $$
}
```
=== "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"
@@ -2653,7 +2811,7 @@ $$
也就是说,底数 $m$ 可以在不影响复杂度的前提下转换。因此我们通常会省略底数 $m$ ,将对数阶直接记为 $O(\log n)$ 。
### 6. &nbsp; 线性对数阶 $O(n \log n)$
### 6. &nbsp; 线性对数阶 $O(n \log n)$ {data-toc-label="线性对数阶"}
线性对数阶常出现于嵌套循环中,两层循环的时间复杂度分别为 $O(\log n)$ 和 $O(n)$ 。相关代码如下:
@@ -2819,6 +2977,21 @@ $$
}
```
=== "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"
@@ -2847,7 +3020,7 @@ $$
主流排序算法的时间复杂度通常为 $O(n \log n)$ ,例如快速排序、归并排序、堆排序等。
### 7. &nbsp; 阶乘阶 $O(n!)$
### 7. &nbsp; 阶乘阶 $O(n!)$ {data-toc-label="阶乘阶"}
阶乘阶对应数学上的“全排列”问题。给定 $n$ 个互不重复的元素,求其所有可能的排列方案,方案数量为:
@@ -3029,6 +3202,22 @@ $$
}
```
=== "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"
@@ -3385,6 +3574,39 @@ $$
}
```
=== "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"