mirror of
https://github.com/krahets/hello-algo.git
synced 2026-04-13 18:00:18 +08:00
build
This commit is contained in:
@@ -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"
|
||||
|
||||
@@ -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 常见的空间复杂度类型 </p>
|
||||
|
||||
### 1. 常数阶 $O(1)$
|
||||
### 1. 常数阶 $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. 线性阶 $O(n)$
|
||||
### 2. 线性阶 $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 递归函数产生的线性阶空间复杂度 </p>
|
||||
|
||||
### 3. 平方阶 $O(n^2)$
|
||||
### 3. 平方阶 $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 递归函数产生的平方阶空间复杂度 </p>
|
||||
|
||||
### 4. 指数阶 $O(2^n)$
|
||||
### 4. 指数阶 $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 满二叉树产生的指数阶空间复杂度 </p>
|
||||
|
||||
### 5. 对数阶 $O(\log n)$
|
||||
### 5. 对数阶 $O(\log n)$ {data-toc-label="对数阶"}
|
||||
|
||||
对数阶常见于分治算法。例如归并排序,输入长度为 $n$ 的数组,每轮递归将数组从中点处划分为两半,形成高度为 $\log n$ 的递归树,使用 $O(\log n)$ 栈帧空间。
|
||||
|
||||
|
||||
@@ -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 常见的时间复杂度类型 </p>
|
||||
|
||||
### 1. 常数阶 $O(1)$
|
||||
### 1. 常数阶 $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. 线性阶 $O(n)$
|
||||
### 2. 线性阶 $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. 平方阶 $O(n^2)$
|
||||
### 3. 平方阶 $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. 指数阶 $O(2^n)$
|
||||
### 4. 指数阶 $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. 对数阶 $O(\log n)$
|
||||
### 5. 对数阶 $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. 线性对数阶 $O(n \log n)$
|
||||
### 6. 线性对数阶 $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. 阶乘阶 $O(n!)$
|
||||
### 7. 阶乘阶 $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"
|
||||
|
||||
Reference in New Issue
Block a user