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
+1 -1
View File
@@ -136,7 +136,7 @@ comments: true
| $n$-queens problem | $n$ 皇后问题 | $n$ 皇后問題 | | $n$-queens problem | $n$ 皇后问题 | $n$ 皇后問題 |
| dynamic programming | 动态规划 | 動態規劃 | | dynamic programming | 动态规划 | 動態規劃 |
| initial state | 初始状态 | 初始狀態 | | initial state | 初始状态 | 初始狀態 |
| state-trasition equation | 状态转移方程 | 狀態轉移方程 | | state-transition equation | 状态转移方程 | 狀態轉移方程 |
| knapsack problem | 背包问题 | 背包問題 | | knapsack problem | 背包问题 | 背包問題 |
| edit distance problem | 编辑距离问题 | 編輯距離問題 | | edit distance problem | 编辑距离问题 | 編輯距離問題 |
| greedy algorithm | 贪心算法 | 貪婪演算法 | | greedy algorithm | 贪心算法 | 貪婪演算法 |
@@ -111,6 +111,12 @@ comments: true
int nums[5] = { 1, 3, 2, 5, 4 }; int nums[5] = { 1, 3, 2, 5, 4 };
``` ```
=== "Kotlin"
```kotlin title="array.kt"
```
=== "Zig" === "Zig"
```zig title="array.zig" ```zig title="array.zig"
@@ -279,6 +285,19 @@ comments: true
} }
``` ```
=== "Kotlin"
```kotlin title="array.kt"
/* 随机访问元素 */
fun randomAccess(nums: IntArray): Int {
// 在区间 [0, nums.size) 中随机抽取一个数字
val randomIndex = ThreadLocalRandom.current().nextInt(0, nums.size)
// 获取并返回随机元素
val randomNum = nums[randomIndex]
return randomNum
}
```
=== "Zig" === "Zig"
```zig title="array.zig" ```zig title="array.zig"
@@ -459,6 +478,20 @@ comments: true
} }
``` ```
=== "Kotlin"
```kotlin title="array.kt"
/* 在数组的索引 index 处插入元素 num */
fun insert(nums: IntArray, num: Int, index: Int) {
// 把索引 index 以及之后的所有元素向后移动一位
for (i in nums.size - 1 downTo index + 1) {
nums[i] = nums[i - 1]
}
// 将 num 赋给 index 处的元素
nums[index] = num
}
```
=== "Zig" === "Zig"
```zig title="array.zig" ```zig title="array.zig"
@@ -620,6 +653,18 @@ comments: true
} }
``` ```
=== "Kotlin"
```kotlin title="array.kt"
/* 删除索引 index 处的元素 */
fun remove(nums: IntArray, index: Int) {
// 把索引 index 之后的所有元素向前移动一位
for (i in index..<nums.size - 1) {
nums[i] = nums[i + 1]
}
}
```
=== "Zig" === "Zig"
```zig title="array.zig" ```zig title="array.zig"
@@ -843,6 +888,23 @@ comments: true
} }
``` ```
=== "Kotlin"
```kotlin title="array.kt"
/* 遍历数组 */
fun traverse(nums: IntArray) {
var count = 0
// 通过索引遍历数组
for (i in nums.indices) {
count += nums[i]
}
// 直接遍历数组元素
for (j: Int in nums) {
count += j
}
}
```
=== "Zig" === "Zig"
```zig title="array.zig" ```zig title="array.zig"
@@ -1018,6 +1080,18 @@ comments: true
} }
``` ```
=== "Kotlin"
```kotlin title="array.kt"
/* 在数组中查找指定元素 */
fun find(nums: IntArray, target: Int): Int {
for (i in nums.indices) {
if (nums[i] == target) return i
}
return -1
}
```
=== "Zig" === "Zig"
```zig title="array.zig" ```zig title="array.zig"
@@ -1225,6 +1299,22 @@ comments: true
} }
``` ```
=== "Kotlin"
```kotlin title="array.kt"
/* 扩展数组长度 */
fun extend(nums: IntArray, enlarge: Int): IntArray {
// 初始化一个扩展长度后的数组
val res = IntArray(nums.size + enlarge)
// 将原数组中的所有元素复制到新数组
for (i in nums.indices) {
res[i] = nums[i]
}
// 返回扩展后的新数组
return res
}
```
=== "Zig" === "Zig"
```zig title="array.zig" ```zig title="array.zig"
@@ -165,6 +165,12 @@ comments: true
} }
``` ```
=== "Kotlin"
```kotlin title=""
```
=== "Zig" === "Zig"
```zig title="" ```zig title=""
@@ -379,6 +385,12 @@ comments: true
n3->next = n4; n3->next = n4;
``` ```
=== "Kotlin"
```kotlin title="linked_list.kt"
```
=== "Zig" === "Zig"
```zig title="linked_list.zig" ```zig title="linked_list.zig"
@@ -534,6 +546,17 @@ comments: true
} }
``` ```
=== "Kotlin"
```kotlin title="linked_list.kt"
/* 在链表的节点 n0 之后插入节点p */
fun insert(n0: ListNode?, p: ListNode?) {
val n1 = n0?.next
p?.next = n1
n0?.next = p
}
```
=== "Zig" === "Zig"
```zig title="linked_list.zig" ```zig title="linked_list.zig"
@@ -723,6 +746,17 @@ comments: true
} }
``` ```
=== "Kotlin"
```kotlin title="linked_list.kt"
/* 删除链表的节点 n0 之后的首个节点 */
fun remove(n0: ListNode?) {
val p = n0?.next
val n1 = p?.next
n0?.next = n1
}
```
=== "Zig" === "Zig"
```zig title="linked_list.zig" ```zig title="linked_list.zig"
@@ -903,6 +937,19 @@ comments: true
} }
``` ```
=== "Kotlin"
```kotlin title="linked_list.kt"
/* 访问链表中索引为 index 的节点 */
fun access(head: ListNode?, index: Int): ListNode? {
var h = head
for (i in 0..<index) {
h = h?.next
}
return h
}
```
=== "Zig" === "Zig"
```zig title="linked_list.zig" ```zig title="linked_list.zig"
@@ -1106,6 +1153,22 @@ comments: true
} }
``` ```
=== "Kotlin"
```kotlin title="linked_list.kt"
/* 在链表中查找值为 target 的首个节点 */
fun find(head: ListNode?, target: Int): Int {
var index = 0
var h = head
while (h != null) {
if (h.value == target) return index
h = h.next
index++
}
return -1
}
```
=== "Zig" === "Zig"
```zig title="linked_list.zig" ```zig title="linked_list.zig"
@@ -1323,6 +1386,12 @@ comments: true
} }
``` ```
=== "Kotlin"
```kotlin title=""
```
=== "Zig" === "Zig"
```zig title="" ```zig title=""
+136
View File
@@ -130,6 +130,12 @@ comments: true
// C 未提供内置动态数组 // C 未提供内置动态数组
``` ```
=== "Kotlin"
```kotlin title="list.kt"
```
=== "Zig" === "Zig"
```zig title="list.zig" ```zig title="list.zig"
@@ -253,6 +259,12 @@ comments: true
// C 未提供内置动态数组 // C 未提供内置动态数组
``` ```
=== "Kotlin"
```kotlin title="list.kt"
```
=== "Zig" === "Zig"
```zig title="list.zig" ```zig title="list.zig"
@@ -478,6 +490,12 @@ comments: true
// C 未提供内置动态数组 // C 未提供内置动态数组
``` ```
=== "Kotlin"
```kotlin title="list.kt"
```
=== "Zig" === "Zig"
```zig title="list.zig" ```zig title="list.zig"
@@ -669,6 +687,12 @@ comments: true
// C 未提供内置动态数组 // C 未提供内置动态数组
``` ```
=== "Kotlin"
```kotlin title="list.kt"
```
=== "Zig" === "Zig"
```zig title="list.zig" ```zig title="list.zig"
@@ -782,6 +806,12 @@ comments: true
// C 未提供内置动态数组 // C 未提供内置动态数组
``` ```
=== "Kotlin"
```kotlin title="list.kt"
```
=== "Zig" === "Zig"
```zig title="list.zig" ```zig title="list.zig"
@@ -877,6 +907,12 @@ comments: true
// C 未提供内置动态数组 // C 未提供内置动态数组
``` ```
=== "Kotlin"
```kotlin title="list.kt"
```
=== "Zig" === "Zig"
```zig title="list.zig" ```zig title="list.zig"
@@ -2035,6 +2071,106 @@ comments: true
} }
``` ```
=== "Kotlin"
```kotlin title="my_list.kt"
/* 列表类 */
class MyList {
private var arr: IntArray = intArrayOf() // 数组(存储列表元素)
private var capacity = 10 // 列表容量
private var size = 0 // 列表长度(当前元素数量)
private var extendRatio = 2 // 每次列表扩容的倍数
/* 构造函数 */
init {
arr = IntArray(capacity)
}
/* 获取列表长度(当前元素数量) */
fun size(): Int {
return size
}
/* 获取列表容量 */
fun capacity(): Int {
return capacity
}
/* 访问元素 */
fun get(index: Int): Int {
// 索引如果越界,则抛出异常,下同
if (index < 0 || index >= size)
throw IndexOutOfBoundsException()
return arr[index]
}
/* 更新元素 */
fun set(index: Int, num: Int) {
if (index < 0 || index >= size)
throw IndexOutOfBoundsException("索引越界")
arr[index] = num
}
/* 在尾部添加元素 */
fun add(num: Int) {
// 元素数量超出容量时,触发扩容机制
if (size == capacity())
extendCapacity()
arr[size] = num
// 更新元素数量
size++
}
/* 在中间插入元素 */
fun insert(index: Int, num: Int) {
if (index < 0 || index >= size)
throw IndexOutOfBoundsException("索引越界")
// 元素数量超出容量时,触发扩容机制
if (size == capacity())
extendCapacity()
// 将索引 index 以及之后的元素都向后移动一位
for (j in size - 1 downTo index)
arr[j + 1] = arr[j]
arr[index] = num
// 更新元素数量
size++
}
/* 删除元素 */
fun remove(index: Int): Int {
if (index < 0 || index >= size)
throw IndexOutOfBoundsException("索引越界")
val num: Int = arr[index]
// 将将索引 index 之后的元素都向前移动一位
for (j in index..<size - 1)
arr[j] = arr[j + 1]
// 更新元素数量
size--
// 返回被删除的元素
return num
}
/* 列表扩容 */
fun extendCapacity() {
// 新建一个长度为原数组 extendRatio 倍的新数组,并将原数组复制到新数组
arr = arr.copyOf(capacity() * extendRatio)
// 更新列表容量
capacity = arr.size
}
/* 将列表转换为数组 */
fun toArray(): IntArray {
val size = size()
// 仅转换有效长度范围内的列表元素
val arr = IntArray(size)
for (i in 0..<size) {
arr[i] = get(i)
}
return arr
}
}
```
=== "Zig" === "Zig"
```zig title="my_list.zig" ```zig title="my_list.zig"
@@ -200,6 +200,23 @@ comments: true
} }
``` ```
=== "Kotlin"
```kotlin title="preorder_traversal_i_compact.kt"
/* 前序遍历:例题一 */
fun preOrder(root: TreeNode?) {
if (root == null) {
return
}
if (root.value == 7) {
// 记录解
res!!.add(root)
}
preOrder(root.left)
preOrder(root.right)
}
```
=== "Zig" === "Zig"
```zig title="preorder_traversal_i_compact.zig" ```zig title="preorder_traversal_i_compact.zig"
@@ -475,6 +492,27 @@ comments: true
} }
``` ```
=== "Kotlin"
```kotlin title="preorder_traversal_ii_compact.kt"
/* 前序遍历:例题二 */
fun preOrder(root: TreeNode?) {
if (root == null) {
return
}
// 尝试
path!!.add(root)
if (root.value == 7) {
// 记录解
res!!.add(ArrayList(path!!))
}
preOrder(root.left)
preOrder(root.right)
// 回退
path!!.removeAt(path!!.size - 1)
}
```
=== "Zig" === "Zig"
```zig title="preorder_traversal_ii_compact.zig" ```zig title="preorder_traversal_ii_compact.zig"
@@ -791,6 +829,28 @@ comments: true
} }
``` ```
=== "Kotlin"
```kotlin title="preorder_traversal_iii_compact.kt"
/* 前序遍历:例题三 */
fun preOrder(root: TreeNode?) {
// 剪枝
if (root == null || root.value == 3) {
return
}
// 尝试
path!!.add(root)
if (root.value == 7) {
// 记录解
res!!.add(ArrayList(path!!))
}
preOrder(root.left)
preOrder(root.right)
// 回退
path!!.removeAt(path!!.size - 1)
}
```
=== "Zig" === "Zig"
```zig title="preorder_traversal_iii_compact.zig" ```zig title="preorder_traversal_iii_compact.zig"
@@ -1096,6 +1156,12 @@ comments: true
} }
``` ```
=== "Kotlin"
```kotlin title=""
```
=== "Zig" === "Zig"
```zig title="" ```zig title=""
@@ -1676,6 +1742,60 @@ comments: true
} }
``` ```
=== "Kotlin"
```kotlin title="preorder_traversal_iii_template.kt"
/* 判断当前状态是否为解 */
fun isSolution(state: List<TreeNode?>): Boolean {
return state.isNotEmpty() && state[state.size - 1]?.value == 7
}
/* 记录解 */
fun recordSolution(state: MutableList<TreeNode?>?, res: MutableList<List<TreeNode?>?>) {
res.add(state?.let { ArrayList(it) })
}
/* 判断在当前状态下,该选择是否合法 */
fun isValid(state: List<TreeNode?>?, choice: TreeNode?): Boolean {
return choice != null && choice.value != 3
}
/* 更新状态 */
fun makeChoice(state: MutableList<TreeNode?>, choice: TreeNode?) {
state.add(choice)
}
/* 恢复状态 */
fun undoChoice(state: MutableList<TreeNode?>, choice: TreeNode?) {
state.removeLast()
}
/* 回溯算法:例题三 */
fun backtrack(
state: MutableList<TreeNode?>,
choices: List<TreeNode?>,
res: MutableList<List<TreeNode?>?>
) {
// 检查是否为解
if (isSolution(state)) {
// 记录解
recordSolution(state, res)
}
// 遍历所有选择
for (choice in choices) {
// 剪枝:检查选择是否合法
if (isValid(state, choice)) {
// 尝试:做出选择,更新状态
makeChoice(state, choice)
// 进行下一轮选择
backtrack(state, listOf(choice!!.left, choice.right), res)
// 回退:撤销选择,恢复到之前的状态
undoChoice(state, choice)
}
}
}
```
=== "Zig" === "Zig"
```zig title="preorder_traversal_iii_template.zig" ```zig title="preorder_traversal_iii_template.zig"
@@ -639,6 +639,73 @@ comments: true
} }
``` ```
=== "Kotlin"
```kotlin title="n_queens.kt"
/* 回溯算法:n 皇后 */
fun backtrack(
row: Int,
n: Int,
state: List<MutableList<String>>,
res: MutableList<List<List<String>>?>,
cols: BooleanArray,
diags1: BooleanArray,
diags2: BooleanArray
) {
// 当放置完所有行时,记录解
if (row == n) {
val copyState: MutableList<List<String>> = ArrayList()
for (sRow in state) {
copyState.add(ArrayList(sRow))
}
res.add(copyState)
return
}
// 遍历所有列
for (col in 0..<n) {
// 计算该格子对应的主对角线和次对角线
val diag1 = row - col + n - 1
val diag2 = row + col
// 剪枝:不允许该格子所在列、主对角线、次对角线上存在皇后
if (!cols[col] && !diags1[diag1] && !diags2[diag2]) {
// 尝试:将皇后放置在该格子
state[row][col] = "Q"
diags2[diag2] = true
diags1[diag1] = diags2[diag2]
cols[col] = diags1[diag1]
// 放置下一行
backtrack(row + 1, n, state, res, cols, diags1, diags2)
// 回退:将该格子恢复为空位
state[row][col] = "#"
diags2[diag2] = false
diags1[diag1] = diags2[diag2]
cols[col] = diags1[diag1]
}
}
}
/* 求解 n 皇后 */
fun nQueens(n: Int): List<List<List<String>>?> {
// 初始化 n*n 大小的棋盘,其中 'Q' 代表皇后,'#' 代表空位
val state: MutableList<MutableList<String>> = ArrayList()
for (i in 0..<n) {
val row: MutableList<String> = ArrayList()
for (j in 0..<n) {
row.add("#")
}
state.add(row)
}
val cols = BooleanArray(n) // 记录列是否有皇后
val diags1 = BooleanArray(2 * n - 1) // 记录主对角线上是否有皇后
val diags2 = BooleanArray(2 * n - 1) // 记录次对角线上是否有皇后
val res: MutableList<List<List<String>>?> = ArrayList()
backtrack(0, n, state, res, cols, diags1, diags2)
return res
}
```
=== "Zig" === "Zig"
```zig title="n_queens.zig" ```zig title="n_queens.zig"
@@ -463,6 +463,46 @@ comments: true
} }
``` ```
=== "Kotlin"
```kotlin title="permutations_i.kt"
/* 回溯算法:全排列 I */
fun backtrack(
state: MutableList<Int>,
choices: IntArray,
selected: BooleanArray,
res: MutableList<List<Int>?>
) {
// 当状态长度等于元素数量时,记录解
if (state.size == choices.size) {
res.add(ArrayList(state))
return
}
// 遍历所有选择
for (i in choices.indices) {
val choice = choices[i]
// 剪枝:不允许重复选择元素
if (!selected[i]) {
// 尝试:做出选择,更新状态
selected[i] = true
state.add(choice)
// 进行下一轮选择
backtrack(state, choices, selected, res)
// 回退:撤销选择,恢复到之前的状态
selected[i] = false
state.removeAt(state.size - 1)
}
}
}
/* 全排列 I */
fun permutationsI(nums: IntArray): List<List<Int>?> {
val res: MutableList<List<Int>?> = ArrayList()
backtrack(ArrayList(), nums, BooleanArray(nums.size), res)
return res
}
```
=== "Zig" === "Zig"
```zig title="permutations_i.zig" ```zig title="permutations_i.zig"
@@ -939,6 +979,48 @@ comments: true
} }
``` ```
=== "Kotlin"
```kotlin title="permutations_ii.kt"
/* 回溯算法:全排列 II */
fun backtrack(
state: MutableList<Int>,
choices: IntArray,
selected: BooleanArray,
res: MutableList<MutableList<Int>?>
) {
// 当状态长度等于元素数量时,记录解
if (state.size == choices.size) {
res.add(ArrayList(state))
return
}
// 遍历所有选择
val duplicated: MutableSet<Int> = HashSet()
for (i in choices.indices) {
val choice = choices[i]
// 剪枝:不允许重复选择元素 且 不允许重复选择相等元素
if (!selected[i] && !duplicated.contains(choice)) {
// 尝试:做出选择,更新状态
duplicated.add(choice) // 记录选择过的元素值
selected[i] = true
state.add(choice)
// 进行下一轮选择
backtrack(state, choices, selected, res)
// 回退:撤销选择,恢复到之前的状态
selected[i] = false
state.removeAt(state.size - 1)
}
}
}
/* 全排列 II */
fun permutationsII(nums: IntArray): MutableList<MutableList<Int>?> {
val res: MutableList<MutableList<Int>?> = ArrayList()
backtrack(ArrayList(), nums, BooleanArray(nums.size), res)
return res
}
```
=== "Zig" === "Zig"
```zig title="permutations_ii.zig" ```zig title="permutations_ii.zig"
@@ -426,6 +426,47 @@ comments: true
} }
``` ```
=== "Kotlin"
```kotlin title="subset_sum_i_naive.kt"
/* 回溯算法:子集和 I */
fun backtrack(
state: MutableList<Int>,
target: Int,
total: Int,
choices: IntArray,
res: MutableList<List<Int>?>
) {
// 子集和等于 target 时,记录解
if (total == target) {
res.add(ArrayList(state))
return
}
// 遍历所有选择
for (i in choices.indices) {
// 剪枝:若子集和超过 target ,则跳过该选择
if (total + choices[i] > target) {
continue
}
// 尝试:做出选择,更新元素和 total
state.add(choices[i])
// 进行下一轮选择
backtrack(state, target, total + choices[i], choices, res)
// 回退:撤销选择,恢复到之前的状态
state.removeAt(state.size - 1)
}
}
/* 求解子集和 I(包含重复子集) */
fun subsetSumINaive(nums: IntArray, target: Int): List<List<Int>?> {
val state: MutableList<Int> = ArrayList() // 状态(子集)
val total = 0 // 子集和
val res: MutableList<List<Int>?> = ArrayList() // 结果列表(子集列表)
backtrack(state, target, total, nums, res)
return res
}
```
=== "Zig" === "Zig"
```zig title="subset_sum_i_naive.zig" ```zig title="subset_sum_i_naive.zig"
@@ -915,6 +956,50 @@ comments: true
} }
``` ```
=== "Kotlin"
```kotlin title="subset_sum_i.kt"
/* 回溯算法:子集和 I */
fun backtrack(
state: MutableList<Int>,
target: Int,
choices: IntArray,
start: Int,
res: MutableList<List<Int>?>
) {
// 子集和等于 target 时,记录解
if (target == 0) {
res.add(ArrayList(state))
return
}
// 遍历所有选择
// 剪枝二:从 start 开始遍历,避免生成重复子集
for (i in start..<choices.size) {
// 剪枝一:若子集和超过 target ,则直接结束循环
// 这是因为数组已排序,后边元素更大,子集和一定超过 target
if (target - choices[i] < 0) {
break
}
// 尝试:做出选择,更新 target, start
state.add(choices[i])
// 进行下一轮选择
backtrack(state, target - choices[i], choices, i, res)
// 回退:撤销选择,恢复到之前的状态
state.removeAt(state.size - 1)
}
}
/* 求解子集和 I */
fun subsetSumI(nums: IntArray, target: Int): List<List<Int>?> {
val state: MutableList<Int> = ArrayList() // 状态(子集)
Arrays.sort(nums) // 对 nums 进行排序
val start = 0 // 遍历起始点
val res: MutableList<List<Int>?> = ArrayList() // 结果列表(子集列表)
backtrack(state, target, nums, start, res)
return res
}
```
=== "Zig" === "Zig"
```zig title="subset_sum_i.zig" ```zig title="subset_sum_i.zig"
@@ -1445,6 +1530,55 @@ comments: true
} }
``` ```
=== "Kotlin"
```kotlin title="subset_sum_ii.kt"
/* 回溯算法:子集和 II */
fun backtrack(
state: MutableList<Int>,
target: Int,
choices: IntArray,
start: Int,
res: MutableList<List<Int>?>
) {
// 子集和等于 target 时,记录解
if (target == 0) {
res.add(ArrayList(state))
return
}
// 遍历所有选择
// 剪枝二:从 start 开始遍历,避免生成重复子集
// 剪枝三:从 start 开始遍历,避免重复选择同一元素
for (i in start..<choices.size) {
// 剪枝一:若子集和超过 target ,则直接结束循环
// 这是因为数组已排序,后边元素更大,子集和一定超过 target
if (target - choices[i] < 0) {
break
}
// 剪枝四:如果该元素与左边元素相等,说明该搜索分支重复,直接跳过
if (i > start && choices[i] == choices[i - 1]) {
continue
}
// 尝试:做出选择,更新 target, start
state.add(choices[i])
// 进行下一轮选择
backtrack(state, target - choices[i], choices, i + 1, res)
// 回退:撤销选择,恢复到之前的状态
state.removeAt(state.size - 1)
}
}
/* 求解子集和 II */
fun subsetSumII(nums: IntArray, target: Int): List<List<Int>?> {
val state: MutableList<Int> = ArrayList() // 状态(子集)
Arrays.sort(nums) // 对 nums 进行排序
val start = 0 // 遍历起始点
val res: MutableList<List<Int>?> = ArrayList() // 结果列表(子集列表)
backtrack(state, target, nums, start, res)
return res
}
```
=== "Zig" === "Zig"
```zig title="subset_sum_ii.zig" ```zig title="subset_sum_ii.zig"
@@ -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"
```zig title="iteration.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"
```zig title="iteration.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"
```zig title="iteration.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"
```zig title="iteration.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"
```zig title="recursion.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"
```zig title="recursion.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"
```zig title="recursion.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"
```zig title="recursion.zig" ```zig title="recursion.zig"
@@ -315,6 +315,12 @@ comments: true
} }
``` ```
=== "Kotlin"
```kotlin title=""
```
=== "Zig" === "Zig"
```zig title="" ```zig title=""
@@ -461,6 +467,12 @@ comments: true
} }
``` ```
=== "Kotlin"
```kotlin title=""
```
=== "Zig" === "Zig"
```zig title="" ```zig title=""
@@ -481,9 +493,10 @@ comments: true
for _ in range(n): for _ in range(n):
function() function()
def recur(n: int) -> int: def recur(n: int):
"""递归的空间复杂度为 O(n)""" """递归的空间复杂度为 O(n)"""
if n == 1: return if n == 1:
return
return recur(n - 1) return recur(n - 1)
``` ```
@@ -698,6 +711,12 @@ comments: true
} }
``` ```
=== "Kotlin"
```kotlin title=""
```
=== "Zig" === "Zig"
```zig title="" ```zig title=""
@@ -724,7 +743,7 @@ $$
<p align="center"> 图 2-16 &nbsp; 常见的空间复杂度类型 </p> <p align="center"> 图 2-16 &nbsp; 常见的空间复杂度类型 </p>
### 1. &nbsp; 常数阶 $O(1)$ ### 1. &nbsp; 常数阶 $O(1)$ {data-toc-label="常数阶"}
常数阶常见于数量与输入数据大小 $n$ 无关的常量、变量、对象。 常数阶常见于数量与输入数据大小 $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"
```zig title="space_complexity.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="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> <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$ 成正比的数组、链表、栈、队列等: 线性阶常见于元素数量与 $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"
```zig title="space_complexity.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"
```zig title="space_complexity.zig" ```zig title="space_complexity.zig"
@@ -1490,7 +1568,7 @@ $$
<p align="center"> 图 2-17 &nbsp; 递归函数产生的线性阶空间复杂度 </p> <p align="center"> 图 2-17 &nbsp; 递归函数产生的线性阶空间复杂度 </p>
### 3. &nbsp; 平方阶 $O(n^2)$ ### 3. &nbsp; 平方阶 $O(n^2)$ {data-toc-label="平方阶"}
平方阶常见于矩阵和图,元素数量与 $n$ 成平方关系: 平方阶常见于矩阵和图,元素数量与 $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"
```zig title="space_complexity.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"
```zig title="space_complexity.zig" ```zig title="space_complexity.zig"
@@ -1881,7 +1992,7 @@ $$
<p align="center"> 图 2-18 &nbsp; 递归函数产生的平方阶空间复杂度 </p> <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)$ 空间: 指数阶常见于二叉树。观察图 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"
```zig title="space_complexity.zig" ```zig title="space_complexity.zig"
@@ -2061,7 +2186,7 @@ $$
<p align="center"> 图 2-19 &nbsp; 满二叉树产生的指数阶空间复杂度 </p> <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)$ 栈帧空间。 对数阶常见于分治算法。例如归并排序,输入长度为 $n$ 的数组,每轮递归将数组从中点处划分为两半,形成高度为 $\log n$ 的递归树,使用 $O(\log n)$ 栈帧空间。
@@ -175,6 +175,12 @@ comments: true
} }
``` ```
=== "Kotlin"
```kotlin title=""
```
=== "Zig" === "Zig"
```zig title="" ```zig title=""
@@ -433,6 +439,12 @@ $$
} }
``` ```
=== "Kotlin"
```kotlin title=""
```
=== "Zig" === "Zig"
```zig title="" ```zig title=""
@@ -629,6 +641,12 @@ $$
} }
``` ```
=== "Kotlin"
```kotlin title=""
```
=== "Zig" === "Zig"
```zig title="" ```zig title=""
@@ -888,6 +906,12 @@ $T(n)$ 是一次函数,说明其运行时间的增长趋势是线性的,因
} }
``` ```
=== "Kotlin"
```kotlin title=""
```
=== "Zig" === "Zig"
```zig title="" ```zig title=""
@@ -954,7 +978,7 @@ $$
<p align="center"> 图 2-9 &nbsp; 常见的时间复杂度类型 </p> <p align="center"> 图 2-9 &nbsp; 常见的时间复杂度类型 </p>
### 1. &nbsp; 常数阶 $O(1)$ ### 1. &nbsp; 常数阶 $O(1)$ {data-toc-label="常数阶"}
常数阶的操作数量与输入数据大小 $n$ 无关,即不随着 $n$ 的变化而变化。 常数阶的操作数量与输入数据大小 $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"
```zig title="time_complexity.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="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> <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$ 以线性级别增长。线性阶通常出现在单层循环中: 线性阶的操作数量相对于输入数据大小 $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"
```zig title="time_complexity.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"
```zig title="time_complexity.zig" ```zig title="time_complexity.zig"
@@ -1460,7 +1524,7 @@ $$
值得注意的是,**输入数据大小 $n$ 需根据输入数据的类型来具体确定**。比如在第一个示例中,变量 $n$ 为输入数据大小;在第二个示例中,数组长度 $n$ 为数据大小。 值得注意的是,**输入数据大小 $n$ 需根据输入数据的类型来具体确定**。比如在第一个示例中,变量 $n$ 为输入数据大小;在第二个示例中,数组长度 $n$ 为数据大小。
### 3. &nbsp; 平方阶 $O(n^2)$ ### 3. &nbsp; 平方阶 $O(n^2)$ {data-toc-label="平方阶"}
平方阶的操作数量相对于输入数据大小 $n$ 以平方级别增长。平方阶通常出现在嵌套循环中,外层循环和内层循环的时间复杂度都为 $O(n)$ ,因此总体的时间复杂度为 $O(n^2)$ : 平方阶的操作数量相对于输入数据大小 $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"
```zig title="time_complexity.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"
```zig title="time_complexity.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="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> <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$ 个细胞。 生物学的“细胞分裂”是指数阶增长的典型例子:初始状态为 $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"
```zig title="time_complexity.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"
```zig title="time_complexity.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$ 的反函数。 与指数阶相反,对数阶反映了“每轮缩减到一半”的情况。设输入数据大小为 $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"
```zig title="time_complexity.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"
```zig title="time_complexity.zig" ```zig title="time_complexity.zig"
@@ -2653,7 +2811,7 @@ $$
也就是说,底数 $m$ 可以在不影响复杂度的前提下转换。因此我们通常会省略底数 $m$ ,将对数阶直接记为 $O(\log n)$ 。 也就是说,底数 $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)$ 。相关代码如下: 线性对数阶常出现于嵌套循环中,两层循环的时间复杂度分别为 $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"
```zig title="time_complexity.zig" ```zig title="time_complexity.zig"
@@ -2847,7 +3020,7 @@ $$
主流排序算法的时间复杂度通常为 $O(n \log n)$ ,例如快速排序、归并排序、堆排序等。 主流排序算法的时间复杂度通常为 $O(n \log n)$ ,例如快速排序、归并排序、堆排序等。
### 7. &nbsp; 阶乘阶 $O(n!)$ ### 7. &nbsp; 阶乘阶 $O(n!)$ {data-toc-label="阶乘阶"}
阶乘阶对应数学上的“全排列”问题。给定 $n$ 个互不重复的元素,求其所有可能的排列方案,方案数量为: 阶乘阶对应数学上的“全排列”问题。给定 $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"
```zig title="time_complexity.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"
```zig title="worst_best_time_complexity.zig" ```zig title="worst_best_time_complexity.zig"
@@ -161,6 +161,12 @@ comments: true
bool bools[10]; bool bools[10];
``` ```
=== "Kotlin"
```kotlin title=""
```
=== "Zig" === "Zig"
```zig title="" ```zig title=""
@@ -383,6 +383,42 @@ comments: true
} }
``` ```
=== "Kotlin"
```kotlin title="binary_search_recur.kt"
/* 二分查找:问题 f(i, j) */
fun dfs(
nums: IntArray,
target: Int,
i: Int,
j: Int
): Int {
// 若区间为空,代表无目标元素,则返回 -1
if (i > j) {
return -1
}
// 计算中点索引 m
val m = (i + j) / 2
return if (nums[m] < target) {
// 递归子问题 f(m+1, j)
dfs(nums, target, m + 1, j)
} else if (nums[m] > target) {
// 递归子问题 f(i, m-1)
dfs(nums, target, i, m - 1)
} else {
// 找到目标元素,返回其索引
m
}
}
/* 二分查找 */
fun binarySearch(nums: IntArray, target: Int): Int {
val n = nums.size
// 求解问题 f(0, n-1)
return dfs(nums, target, 0, n - 1)
}
```
=== "Zig" === "Zig"
```zig title="binary_search_recur.zig" ```zig title="binary_search_recur.zig"
@@ -445,6 +445,37 @@ comments: true
} }
``` ```
=== "Kotlin"
```kotlin title="build_tree.kt"
/* 构建二叉树:分治 */
fun dfs(preorder: IntArray, inorderMap: Map<Int?, Int?>, i: Int, l: Int, r: Int): TreeNode? {
// 子树区间为空时终止
if (r - l < 0) return null
// 初始化根节点
val root = TreeNode(preorder[i])
// 查询 m ,从而划分左右子树
val m = inorderMap[preorder[i]]!!
// 子问题:构建左子树
root.left = dfs(preorder, inorderMap, i + 1, l, m - 1)
// 子问题:构建右子树
root.right = dfs(preorder, inorderMap, i + 1 + m - l, m + 1, r)
// 返回根节点
return root
}
/* 构建二叉树 */
fun buildTree(preorder: IntArray, inorder: IntArray): TreeNode? {
// 初始化哈希表,存储 inorder 元素到索引的映射
val inorderMap: MutableMap<Int?, Int?> = HashMap()
for (i in inorder.indices) {
inorderMap[inorder[i]] = i
}
val root = dfs(preorder, inorderMap, 0, 0, inorder.size - 1)
return root
}
```
=== "Zig" === "Zig"
```zig title="build_tree.zig" ```zig title="build_tree.zig"
@@ -473,6 +473,40 @@ comments: true
} }
``` ```
=== "Kotlin"
```kotlin title="hanota.kt"
/* 移动一个圆盘 */
fun move(src: MutableList<Int>, tar: MutableList<Int>) {
// 从 src 顶部拿出一个圆盘
val pan: Int = src.removeAt(src.size - 1)
// 将圆盘放入 tar 顶部
tar.add(pan)
}
/* 求解汉诺塔问题 f(i) */
fun dfs(i: Int, src: MutableList<Int>, buf: MutableList<Int>, tar: MutableList<Int>) {
// 若 src 只剩下一个圆盘,则直接将其移到 tar
if (i == 1) {
move(src, tar)
return
}
// 子问题 f(i-1) :将 src 顶部 i-1 个圆盘借助 tar 移到 buf
dfs(i - 1, src, tar, buf)
// 子问题 f(1) :将 src 剩余一个圆盘移到 tar
move(src, tar)
// 子问题 f(i-1) :将 buf 顶部 i-1 个圆盘借助 src 移到 tar
dfs(i - 1, buf, src, tar)
}
/* 求解汉诺塔问题 */
fun solveHanota(A: MutableList<Int>, B: MutableList<Int>, C: MutableList<Int>) {
val n = A.size
// 将 A 顶部 n 个圆盘借助 B 移到 C
dfs(n, A, B, C)
}
```
=== "Zig" === "Zig"
```zig title="hanota.zig" ```zig title="hanota.zig"
@@ -281,6 +281,26 @@ $$
} }
``` ```
=== "Kotlin"
```kotlin title="min_cost_climbing_stairs_dp.kt"
/* 爬楼梯最小代价:动态规划 */
fun minCostClimbingStairsDP(cost: IntArray): Int {
val n = cost.size - 1
if (n == 1 || n == 2) return cost[n]
// 初始化 dp 表,用于存储子问题的解
val dp = IntArray(n + 1)
// 初始状态:预设最小子问题的解
dp[1] = cost[1]
dp[2] = cost[2]
// 状态转移:从较小子问题逐步求解较大子问题
for (i in 3..n) {
dp[i] = (min(dp[i - 1].toDouble(), dp[i - 2].toDouble()) + cost[i]).toInt()
}
return dp[n]
}
```
=== "Zig" === "Zig"
```zig title="min_cost_climbing_stairs_dp.zig" ```zig title="min_cost_climbing_stairs_dp.zig"
@@ -522,6 +542,24 @@ $$
} }
``` ```
=== "Kotlin"
```kotlin title="min_cost_climbing_stairs_dp.kt"
/* 爬楼梯最小代价:空间优化后的动态规划 */
fun minCostClimbingStairsDPComp(cost: IntArray): Int {
val n = cost.size - 1
if (n == 1 || n == 2) return cost[n]
var a = cost[1]
var b = cost[2]
for (i in 3..n) {
val tmp = b
b = (min(a.toDouble(), tmp.toDouble()) + cost[i]).toInt()
a = tmp
}
return b
}
```
=== "Zig" === "Zig"
```zig title="min_cost_climbing_stairs_dp.zig" ```zig title="min_cost_climbing_stairs_dp.zig"
@@ -858,6 +896,30 @@ $$
} }
``` ```
=== "Kotlin"
```kotlin title="climbing_stairs_constraint_dp.kt"
/* 带约束爬楼梯:动态规划 */
fun climbingStairsConstraintDP(n: Int): Int {
if (n == 1 || n == 2) {
return 1
}
// 初始化 dp 表,用于存储子问题的解
val dp = Array(n + 1) { IntArray(3) }
// 初始状态:预设最小子问题的解
dp[1][1] = 1
dp[1][2] = 0
dp[2][1] = 0
dp[2][2] = 1
// 状态转移:从较小子问题逐步求解较大子问题
for (i in 3..n) {
dp[i][1] = dp[i - 1][2]
dp[i][2] = dp[i - 2][1] + dp[i - 2][2]
}
return dp[n][1] + dp[n][2]
}
```
=== "Zig" === "Zig"
```zig title="climbing_stairs_constraint_dp.zig" ```zig title="climbing_stairs_constraint_dp.zig"
@@ -345,6 +345,31 @@ $$
} }
``` ```
=== "Kotlin"
```kotlin title="min_path_sum.kt"
/* 最小路径和:暴力搜索 */
fun minPathSumDFS(
grid: Array<Array<Int>>,
i: Int,
j: Int
): Int {
// 若为左上角单元格,则终止搜索
if (i == 0 && j == 0) {
return grid[0][0]
}
// 若行列索引越界,则返回 +∞ 代价
if (i < 0 || j < 0) {
return Int.MAX_VALUE
}
// 计算从左上角到 (i-1, j) 和 (i, j-1) 的最小路径代价
val up = minPathSumDFS(grid, i - 1, j)
val left = minPathSumDFS(grid, i, j - 1)
// 返回从左上角到 (i, j) 的最小路径代价
return (min(left.toDouble(), up.toDouble()) + grid[i][j]).toInt()
}
```
=== "Zig" === "Zig"
```zig title="min_path_sum.zig" ```zig title="min_path_sum.zig"
@@ -675,6 +700,37 @@ $$
} }
``` ```
=== "Kotlin"
```kotlin title="min_path_sum.kt"
/* 最小路径和:记忆化搜索 */
fun minPathSumDFSMem(
grid: Array<Array<Int>>,
mem: Array<Array<Int>>,
i: Int,
j: Int
): Int {
// 若为左上角单元格,则终止搜索
if (i == 0 && j == 0) {
return grid[0][0]
}
// 若行列索引越界,则返回 +∞ 代价
if (i < 0 || j < 0) {
return Int.MAX_VALUE
}
// 若已有记录,则直接返回
if (mem[i][j] != -1) {
return mem[i][j]
}
// 左边和上边单元格的最小路径代价
val up = minPathSumDFSMem(grid, mem, i - 1, j)
val left = minPathSumDFSMem(grid, mem, i, j - 1)
// 记录并返回左上角到 (i, j) 的最小路径代价
mem[i][j] = (min(left.toDouble(), up.toDouble()) + grid[i][j]).toInt()
return mem[i][j]
}
```
=== "Zig" === "Zig"
```zig title="min_path_sum.zig" ```zig title="min_path_sum.zig"
@@ -1026,6 +1082,35 @@ $$
} }
``` ```
=== "Kotlin"
```kotlin title="min_path_sum.kt"
/* 最小路径和:动态规划 */
fun minPathSumDP(grid: Array<Array<Int>>): Int {
val n = grid.size
val m = grid[0].size
// 初始化 dp 表
val dp = Array(n) { IntArray(m) }
dp[0][0] = grid[0][0]
// 状态转移:首行
for (j in 1..<m) {
dp[0][j] = dp[0][j - 1] + grid[0][j]
}
// 状态转移:首列
for (i in 1..<n) {
dp[i][0] = dp[i - 1][0] + grid[i][0]
}
// 状态转移:其余行和列
for (i in 1..<n) {
for (j in 1..<m) {
dp[i][j] =
(min(dp[i][j - 1].toDouble(), dp[i - 1][j].toDouble()) + grid[i][j]).toInt()
}
}
return dp[n - 1][m - 1]
}
```
=== "Zig" === "Zig"
```zig title="min_path_sum.zig" ```zig title="min_path_sum.zig"
@@ -1393,6 +1478,33 @@ $$
} }
``` ```
=== "Kotlin"
```kotlin title="min_path_sum.kt"
/* 最小路径和:空间优化后的动态规划 */
fun minPathSumDPComp(grid: Array<Array<Int>>): Int {
val n = grid.size
val m = grid[0].size
// 初始化 dp 表
val dp = IntArray(m)
// 状态转移:首行
dp[0] = grid[0][0]
for (j in 1..<m) {
dp[j] = dp[j - 1] + grid[0][j]
}
// 状态转移:其余行
for (i in 1..<n) {
// 状态转移:首列
dp[0] = dp[0] + grid[i][0]
// 状态转移:其余列
for (j in 1..<m) {
dp[j] = (min(dp[j - 1].toDouble(), dp[j].toDouble()) + grid[i][j]).toInt()
}
}
return dp[m - 1]
}
```
=== "Zig" === "Zig"
```zig title="min_path_sum.zig" ```zig title="min_path_sum.zig"
@@ -420,6 +420,41 @@ $$
} }
``` ```
=== "Kotlin"
```kotlin title="edit_distance.kt"
/* 编辑距离:动态规划 */
fun editDistanceDP(s: String, t: String): Int {
val n = s.length
val m = t.length
val dp = Array(n + 1) { IntArray(m + 1) }
// 状态转移:首行首列
for (i in 1..n) {
dp[i][0] = i
}
for (j in 1..m) {
dp[0][j] = j
}
// 状态转移:其余行和列
for (i in 1..n) {
for (j in 1..m) {
if (s[i - 1] == t[j - 1]) {
// 若两字符相等,则直接跳过此两字符
dp[i][j] = dp[i - 1][j - 1]
} else {
// 最少编辑步数 = 插入、删除、替换这三种操作的最少编辑步数 + 1
dp[i][j] =
(min(
min(dp[i][j - 1].toDouble(), dp[i - 1][j].toDouble()),
dp[i - 1][j - 1].toDouble()
) + 1).toInt()
}
}
}
return dp[n][m]
}
```
=== "Zig" === "Zig"
```zig title="edit_distance.zig" ```zig title="edit_distance.zig"
@@ -875,6 +910,40 @@ $$
} }
``` ```
=== "Kotlin"
```kotlin title="edit_distance.kt"
/* 编辑距离:空间优化后的动态规划 */
fun editDistanceDPComp(s: String, t: String): Int {
val n = s.length
val m = t.length
val dp = IntArray(m + 1)
// 状态转移:首行
for (j in 1..m) {
dp[j] = j
}
// 状态转移:其余行
for (i in 1..n) {
// 状态转移:首列
var leftup = dp[0] // 暂存 dp[i-1, j-1]
dp[0] = i
// 状态转移:其余列
for (j in 1..m) {
val temp = dp[j]
if (s[i - 1] == t[j - 1]) {
// 若两字符相等,则直接跳过此两字符
dp[j] = leftup
} else {
// 最少编辑步数 = 插入、删除、替换这三种操作的最少编辑步数 + 1
dp[j] = (min(min(dp[j - 1].toDouble(), dp[j].toDouble()), leftup.toDouble()) + 1).toInt()
}
leftup = temp // 更新为下一轮的 dp[i-1, j-1]
}
}
return dp[m]
}
```
=== "Zig" === "Zig"
```zig title="edit_distance.zig" ```zig title="edit_distance.zig"
@@ -356,6 +356,39 @@ comments: true
} }
``` ```
=== "Kotlin"
```kotlin title="climbing_stairs_backtrack.kt"
/* 回溯 */
fun backtrack(
choices: List<Int>,
state: Int,
n: Int,
res: MutableList<Int>
) {
// 当爬到第 n 阶时,方案数量加 1
if (state == n) res[0] = res[0] + 1
// 遍历所有选择
for (choice in choices) {
// 剪枝:不允许越过第 n 阶
if (state + choice > n) continue
// 尝试:做出选择,更新状态
backtrack(choices, state + choice, n, res)
// 回退
}
}
/* 爬楼梯:回溯 */
fun climbingStairsBacktrack(n: Int): Int {
val choices = mutableListOf(1, 2) // 可选择向上爬 1 阶或 2 阶
val state = 0 // 从第 0 阶开始爬
val res = ArrayList<Int>()
res.add(0) // 使用 res[0] 记录方案数量
backtrack(choices, state, n, res)
return res[0]
}
```
=== "Zig" === "Zig"
```zig title="climbing_stairs_backtrack.zig" ```zig title="climbing_stairs_backtrack.zig"
@@ -629,6 +662,24 @@ $$
} }
``` ```
=== "Kotlin"
```kotlin title="climbing_stairs_dfs.kt"
/* 搜索 */
fun dfs(i: Int): Int {
// 已知 dp[1] 和 dp[2] ,返回之
if (i == 1 || i == 2) return i
// dp[i] = dp[i-1] + dp[i-2]
val count = dfs(i - 1) + dfs(i - 2)
return count
}
/* 爬楼梯:搜索 */
fun climbingStairsDFS(n: Int): Int {
return dfs(n)
}
```
=== "Zig" === "Zig"
```zig title="climbing_stairs_dfs.zig" ```zig title="climbing_stairs_dfs.zig"
@@ -967,6 +1018,31 @@ $$
} }
``` ```
=== "Kotlin"
```kotlin title="climbing_stairs_dfs_mem.kt"
/* 记忆化搜索 */
fun dfs(i: Int, mem: IntArray): Int {
// 已知 dp[1] 和 dp[2] ,返回之
if (i == 1 || i == 2) return i
// 若存在记录 dp[i] ,则直接返回之
if (mem[i] != -1) return mem[i]
// dp[i] = dp[i-1] + dp[i-2]
val count = dfs(i - 1, mem) + dfs(i - 2, mem)
// 记录 dp[i]
mem[i] = count
return count
}
/* 爬楼梯:记忆化搜索 */
fun climbingStairsDFSMem(n: Int): Int {
// mem[i] 记录爬到第 i 阶的方案总数,-1 代表无记录
val mem = IntArray(n + 1)
Arrays.fill(mem, -1)
return dfs(n, mem)
}
```
=== "Zig" === "Zig"
```zig title="climbing_stairs_dfs_mem.zig" ```zig title="climbing_stairs_dfs_mem.zig"
@@ -1234,6 +1310,25 @@ $$
} }
``` ```
=== "Kotlin"
```kotlin title="climbing_stairs_dp.kt"
/* 爬楼梯:动态规划 */
fun climbingStairsDP(n: Int): Int {
if (n == 1 || n == 2) return n
// 初始化 dp 表,用于存储子问题的解
val dp = IntArray(n + 1)
// 初始状态:预设最小子问题的解
dp[1] = 1
dp[2] = 2
// 状态转移:从较小子问题逐步求解较大子问题
for (i in 3..n) {
dp[i] = dp[i - 1] + dp[i - 2]
}
return dp[n]
}
```
=== "Zig" === "Zig"
```zig title="climbing_stairs_dp.zig" ```zig title="climbing_stairs_dp.zig"
@@ -1462,6 +1557,23 @@ $$
} }
``` ```
=== "Kotlin"
```kotlin title="climbing_stairs_dp.kt"
/* 爬楼梯:空间优化后的动态规划 */
fun climbingStairsDPComp(n: Int): Int {
if (n == 1 || n == 2) return n
var a = 1
var b = 2
for (i in 3..n) {
val tmp = b
b += a
a = tmp
}
return b
}
```
=== "Zig" === "Zig"
```zig title="climbing_stairs_dp.zig" ```zig title="climbing_stairs_dp.zig"
@@ -295,6 +295,32 @@ $$
} }
``` ```
=== "Kotlin"
```kotlin title="knapsack.kt"
/* 0-1 背包:暴力搜索 */
fun knapsackDFS(
wgt: IntArray,
value: IntArray,
i: Int,
c: Int
): Int {
// 若已选完所有物品或背包无剩余容量,则返回价值 0
if (i == 0 || c == 0) {
return 0
}
// 若超过背包容量,则只能选择不放入背包
if (wgt[i - 1] > c) {
return knapsackDFS(wgt, value, i - 1, c)
}
// 计算不放入和放入物品 i 的最大价值
val no = knapsackDFS(wgt, value, i - 1, c)
val yes = knapsackDFS(wgt, value, i - 1, c - wgt[i - 1]) + value[i - 1]
// 返回两种方案中价值更大的那一个
return max(no.toDouble(), yes.toDouble()).toInt()
}
```
=== "Zig" === "Zig"
```zig title="knapsack.zig" ```zig title="knapsack.zig"
@@ -633,6 +659,38 @@ $$
} }
``` ```
=== "Kotlin"
```kotlin title="knapsack.kt"
/* 0-1 背包:记忆化搜索 */
fun knapsackDFSMem(
wgt: IntArray,
value: IntArray,
mem: Array<IntArray>,
i: Int,
c: Int
): Int {
// 若已选完所有物品或背包无剩余容量,则返回价值 0
if (i == 0 || c == 0) {
return 0
}
// 若已有记录,则直接返回
if (mem[i][c] != -1) {
return mem[i][c]
}
// 若超过背包容量,则只能选择不放入背包
if (wgt[i - 1] > c) {
return knapsackDFSMem(wgt, value, mem, i - 1, c)
}
// 计算不放入和放入物品 i 的最大价值
val no = knapsackDFSMem(wgt, value, mem, i - 1, c)
val yes = knapsackDFSMem(wgt, value, mem, i - 1, c - wgt[i - 1]) + value[i - 1]
// 记录并返回两种方案中价值更大的那一个
mem[i][c] = max(no.toDouble(), yes.toDouble()).toInt()
return mem[i][c]
}
```
=== "Zig" === "Zig"
```zig title="knapsack.zig" ```zig title="knapsack.zig"
@@ -962,6 +1020,35 @@ $$
} }
``` ```
=== "Kotlin"
```kotlin title="knapsack.kt"
/* 0-1 背包:动态规划 */
fun knapsackDP(
wgt: IntArray,
value: IntArray,
cap: Int
): Int {
val n = wgt.size
// 初始化 dp 表
val dp = Array(n + 1) { IntArray(cap + 1) }
// 状态转移
for (i in 1..n) {
for (c in 1..cap) {
if (wgt[i - 1] > c) {
// 若超过背包容量,则不选物品 i
dp[i][c] = dp[i - 1][c]
} else {
// 不选和选物品 i 这两种方案的较大值
dp[i][c] = max(dp[i - 1][c].toDouble(), (dp[i - 1][c - wgt[i - 1]] + value[i - 1]).toDouble())
.toInt()
}
}
}
return dp[n][cap]
}
```
=== "Zig" === "Zig"
```zig title="knapsack.zig" ```zig title="knapsack.zig"
@@ -1321,6 +1408,33 @@ $$
} }
``` ```
=== "Kotlin"
```kotlin title="knapsack.kt"
/* 0-1 背包:空间优化后的动态规划 */
fun knapsackDPComp(
wgt: IntArray,
value: IntArray,
cap: Int
): Int {
val n = wgt.size
// 初始化 dp 表
val dp = IntArray(cap + 1)
// 状态转移
for (i in 1..n) {
// 倒序遍历
for (c in cap downTo 1) {
if (wgt[i - 1] <= c) {
// 不选和选物品 i 这两种方案的较大值
dp[c] =
max(dp[c].toDouble(), (dp[c - wgt[i - 1]] + value[i - 1]).toDouble()).toInt()
}
}
}
return dp[cap]
}
```
=== "Zig" === "Zig"
```zig title="knapsack.zig" ```zig title="knapsack.zig"
@@ -323,6 +323,35 @@ $$
} }
``` ```
=== "Kotlin"
```kotlin title="unbounded_knapsack.kt"
/* 完全背包:动态规划 */
fun unboundedKnapsackDP(
wgt: IntArray,
value: IntArray,
cap: Int
): Int {
val n = wgt.size
// 初始化 dp 表
val dp = Array(n + 1) { IntArray(cap + 1) }
// 状态转移
for (i in 1..n) {
for (c in 1..cap) {
if (wgt[i - 1] > c) {
// 若超过背包容量,则不选物品 i
dp[i][c] = dp[i - 1][c]
} else {
// 不选和选物品 i 这两种方案的较大值
dp[i][c] = max(dp[i - 1][c].toDouble(), (dp[i][c - wgt[i - 1]] + value[i - 1]).toDouble())
.toInt()
}
}
}
return dp[n][cap]
}
```
=== "Zig" === "Zig"
```zig title="unbounded_knapsack.zig" ```zig title="unbounded_knapsack.zig"
@@ -648,6 +677,35 @@ $$
} }
``` ```
=== "Kotlin"
```kotlin title="unbounded_knapsack.kt"
/* 完全背包:空间优化后的动态规划 */
fun unboundedKnapsackDPComp(
wgt: IntArray,
value: IntArray,
cap: Int
): Int {
val n = wgt.size
// 初始化 dp 表
val dp = IntArray(cap + 1)
// 状态转移
for (i in 1..n) {
for (c in 1..cap) {
if (wgt[i - 1] > c) {
// 若超过背包容量,则不选物品 i
dp[c] = dp[c]
} else {
// 不选和选物品 i 这两种方案的较大值
dp[c] =
max(dp[c].toDouble(), (dp[c - wgt[i - 1]] + value[i - 1]).toDouble()).toInt()
}
}
}
return dp[cap]
}
```
=== "Zig" === "Zig"
```zig title="unbounded_knapsack.zig" ```zig title="unbounded_knapsack.zig"
@@ -1063,6 +1121,36 @@ $$
} }
``` ```
=== "Kotlin"
```kotlin title="coin_change.kt"
/* 零钱兑换:动态规划 */
fun coinChangeDP(coins: IntArray, amt: Int): Int {
val n = coins.size
val MAX = amt + 1
// 初始化 dp 表
val dp = Array(n + 1) { IntArray(amt + 1) }
// 状态转移:首行首列
for (a in 1..amt) {
dp[0][a] = MAX
}
// 状态转移:其余行和列
for (i in 1..n) {
for (a in 1..amt) {
if (coins[i - 1] > a) {
// 若超过目标金额,则不选硬币 i
dp[i][a] = dp[i - 1][a]
} else {
// 不选和选硬币 i 这两种方案的较小值
dp[i][a] = min(dp[i - 1][a].toDouble(), (dp[i][a - coins[i - 1]] + 1).toDouble())
.toInt()
}
}
}
return if (dp[n][amt] != MAX) dp[n][amt] else -1
}
```
=== "Zig" === "Zig"
```zig title="coin_change.zig" ```zig title="coin_change.zig"
@@ -1453,6 +1541,33 @@ $$
} }
``` ```
=== "Kotlin"
```kotlin title="coin_change.kt"
/* 零钱兑换:空间优化后的动态规划 */
fun coinChangeDPComp(coins: IntArray, amt: Int): Int {
val n = coins.size
val MAX = amt + 1
// 初始化 dp 表
val dp = IntArray(amt + 1)
Arrays.fill(dp, MAX)
dp[0] = 0
// 状态转移
for (i in 1..n) {
for (a in 1..amt) {
if (coins[i - 1] > a) {
// 若超过目标金额,则不选硬币 i
dp[a] = dp[a]
} else {
// 不选和选硬币 i 这两种方案的较小值
dp[a] = min(dp[a].toDouble(), (dp[a - coins[i - 1]] + 1).toDouble()).toInt()
}
}
}
return if (dp[amt] != MAX) dp[amt] else -1
}
```
=== "Zig" === "Zig"
```zig title="coin_change.zig" ```zig title="coin_change.zig"
@@ -1832,6 +1947,34 @@ $$
} }
``` ```
=== "Kotlin"
```kotlin title="coin_change_ii.kt"
/* 零钱兑换 II:动态规划 */
fun coinChangeIIDP(coins: IntArray, amt: Int): Int {
val n = coins.size
// 初始化 dp 表
val dp = Array(n + 1) { IntArray(amt + 1) }
// 初始化首列
for (i in 0..n) {
dp[i][0] = 1
}
// 状态转移
for (i in 1..n) {
for (a in 1..amt) {
if (coins[i - 1] > a) {
// 若超过目标金额,则不选硬币 i
dp[i][a] = dp[i - 1][a]
} else {
// 不选和选硬币 i 这两种方案之和
dp[i][a] = dp[i - 1][a] + dp[i][a - coins[i - 1]]
}
}
}
return dp[n][amt]
}
```
=== "Zig" === "Zig"
```zig title="coin_change_ii.zig" ```zig title="coin_change_ii.zig"
@@ -2145,6 +2288,31 @@ $$
} }
``` ```
=== "Kotlin"
```kotlin title="coin_change_ii.kt"
/* 零钱兑换 II:空间优化后的动态规划 */
fun coinChangeIIDPComp(coins: IntArray, amt: Int): Int {
val n = coins.size
// 初始化 dp 表
val dp = IntArray(amt + 1)
dp[0] = 1
// 状态转移
for (i in 1..n) {
for (a in 1..amt) {
if (coins[i - 1] > a) {
// 若超过目标金额,则不选硬币 i
dp[a] = dp[a]
} else {
// 不选和选硬币 i 这两种方案之和
dp[a] = dp[a] + dp[a - coins[i - 1]]
}
}
}
return dp[amt]
}
```
=== "Zig" === "Zig"
```zig title="coin_change_ii.zig" ```zig title="coin_change_ii.zig"
+160
View File
@@ -1039,6 +1039,91 @@ comments: true
} }
``` ```
=== "Kotlin"
```kotlin title="graph_adjacency_matrix.kt"
/* 基于邻接矩阵实现的无向图类 */
class GraphAdjMat(vertices: IntArray, edges: Array<IntArray>) {
val vertices: MutableList<Int> = ArrayList() // 顶点列表,元素代表“顶点值”,索引代表“顶点索引”
val adjMat: MutableList<MutableList<Int>> = ArrayList() // 邻接矩阵,行列索引对应“顶点索引”
/* 构造函数 */
init {
// 添加顶点
for (vertex in vertices) {
addVertex(vertex)
}
// 添加边
// 请注意,edges 元素代表顶点索引,即对应 vertices 元素索引
for (edge in edges) {
addEdge(edge[0], edge[1])
}
}
/* 获取顶点数量 */
fun size(): Int {
return vertices.size
}
/* 添加顶点 */
fun addVertex(value: Int) {
val n = size()
// 向顶点列表中添加新顶点的值
vertices.add(value)
// 在邻接矩阵中添加一行
val newRow: MutableList<Int> = mutableListOf()
for (j in 0..<n) {
newRow.add(0)
}
adjMat.add(newRow)
// 在邻接矩阵中添加一列
for (row in adjMat) {
row.add(0)
}
}
/* 删除顶点 */
fun removeVertex(index: Int) {
if (index >= size()) throw IndexOutOfBoundsException()
// 在顶点列表中移除索引 index 的顶点
vertices.removeAt(index)
// 在邻接矩阵中删除索引 index 的行
adjMat.removeAt(index)
// 在邻接矩阵中删除索引 index 的列
for (row in adjMat) {
row.removeAt(index)
}
}
/* 添加边 */
// 参数 i, j 对应 vertices 元素索引
fun addEdge(i: Int, j: Int) {
// 索引越界与相等处理
if (i < 0 || j < 0 || i >= size() || j >= size() || i == j) throw java.lang.IndexOutOfBoundsException()
// 在无向图中,邻接矩阵关于主对角线对称,即满足 (i, j) == (j, i)
adjMat[i][j] = 1;
adjMat[j][i] = 1;
}
/* 删除边 */
// 参数 i, j 对应 vertices 元素索引
fun removeEdge(i: Int, j: Int) {
// 索引越界与相等处理
if (i < 0 || j < 0 || i >= size() || j >= size() || i == j) throw java.lang.IndexOutOfBoundsException()
adjMat[i][j] = 0;
adjMat[j][i] = 0;
}
/* 打印邻接矩阵 */
fun print() {
print("顶点列表 = ")
println(vertices);
println("邻接矩阵 =");
printMatrix(adjMat)
}
}
```
=== "Zig" === "Zig"
```zig title="graph_adjacency_matrix.zig" ```zig title="graph_adjacency_matrix.zig"
@@ -2061,6 +2146,81 @@ comments: true
} }
``` ```
=== "Kotlin"
```kotlin title="graph_adjacency_list.kt"
/* 基于邻接表实现的无向图类 */
class GraphAdjList(edges: Array<Array<Vertex?>>) {
// 邻接表,key:顶点,value:该顶点的所有邻接顶点
val adjList: MutableMap<Vertex, MutableList<Vertex>> = HashMap()
/* 构造函数 */
init {
// 添加所有顶点和边
for (edge in edges) {
addVertex(edge[0]!!);
addVertex(edge[1]!!);
addEdge(edge[0]!!, edge[1]!!);
}
}
/* 获取顶点数量 */
fun size(): Int {
return adjList.size
}
/* 添加边 */
fun addEdge(vet1: Vertex, vet2: Vertex) {
if (!adjList.containsKey(vet1) || !adjList.containsKey(vet2) || vet1 == vet2)
throw IllegalArgumentException()
// 添加边 vet1 - vet2
adjList[vet1]?.add(vet2)
adjList[vet2]?.add(vet1);
}
/* 删除边 */
fun removeEdge(vet1: Vertex, vet2: Vertex) {
if (!adjList.containsKey(vet1) || !adjList.containsKey(vet2) || vet1 == vet2)
throw IllegalArgumentException()
// 删除边 vet1 - vet2
adjList[vet1]?.remove(vet2);
adjList[vet2]?.remove(vet1);
}
/* 添加顶点 */
fun addVertex(vet: Vertex) {
if (adjList.containsKey(vet))
return
// 在邻接表中添加一个新链表
adjList[vet] = mutableListOf()
}
/* 删除顶点 */
fun removeVertex(vet: Vertex) {
if (!adjList.containsKey(vet))
throw IllegalArgumentException()
// 在邻接表中删除顶点 vet 对应的链表
adjList.remove(vet);
// 遍历其他顶点的链表,删除所有包含 vet 的边
for (list in adjList.values) {
list.remove(vet)
}
}
/* 打印邻接表 */
fun print() {
println("邻接表 =")
for (pair in adjList.entries) {
val tmp = ArrayList<Int>()
for (vertex in pair.value) {
tmp.add(vertex.value)
}
println("${pair.key.value}: $tmp,")
}
}
}
```
=== "Zig" === "Zig"
```zig title="graph_adjacency_list.zig" ```zig title="graph_adjacency_list.zig"
+66
View File
@@ -413,6 +413,37 @@ BFS 通常借助队列来实现,代码如下所示。队列具有“先入先
} }
``` ```
=== "Kotlin"
```kotlin title="graph_bfs.kt"
/* 广度优先遍历 */
// 使用邻接表来表示图,以便获取指定顶点的所有邻接顶点
fun graphBFS(graph: GraphAdjList, startVet: Vertex): List<Vertex> {
// 顶点遍历序列
val res: MutableList<Vertex> = ArrayList()
// 哈希表,用于记录已被访问过的顶点
val visited: MutableSet<Vertex> = HashSet()
visited.add(startVet)
// 队列用于实现 BFS
val que: Queue<Vertex> = LinkedList()
que.offer(startVet)
// 以顶点 vet 为起点,循环直至访问完所有顶点
while (!que.isEmpty()) {
val vet = que.poll() // 队首顶点出队
res.add(vet) // 记录访问顶点
// 遍历该顶点的所有邻接顶点
for (adjVet in graph.adjList[vet]!!) {
if (visited.contains(adjVet)) continue // 跳过已被访问的顶点
que.offer(adjVet) // 只入队未访问的顶点
visited.add(adjVet) // 标记该顶点已被访问
}
}
// 返回顶点遍历序列
return res
}
```
=== "Zig" === "Zig"
```zig title="graph_bfs.zig" ```zig title="graph_bfs.zig"
@@ -819,6 +850,41 @@ BFS 通常借助队列来实现,代码如下所示。队列具有“先入先
} }
``` ```
=== "Kotlin"
```kotlin title="graph_dfs.kt"
/* 深度优先遍历辅助函数 */
fun dfs(
graph: GraphAdjList,
visited: MutableSet<Vertex?>,
res: MutableList<Vertex?>,
vet: Vertex?
) {
res.add(vet) // 记录访问顶点
visited.add(vet) // 标记该顶点已被访问
// 遍历该顶点的所有邻接顶点
for (adjVet in graph.adjList[vet]!!) {
if (visited.contains(adjVet)) continue // 跳过已被访问的顶点
// 递归访问邻接顶点
dfs(graph, visited, res, adjVet)
}
}
/* 深度优先遍历 */
// 使用邻接表来表示图,以便获取指定顶点的所有邻接顶点
fun graphDFS(
graph: GraphAdjList,
startVet: Vertex?
): List<Vertex?> {
// 顶点遍历序列
val res: MutableList<Vertex?> = ArrayList()
// 哈希表,用于记录已被访问过的顶点
val visited: MutableSet<Vertex?> = HashSet()
dfs(graph, visited, res, startVet)
return res
}
```
=== "Zig" === "Zig"
```zig title="graph_dfs.zig" ```zig title="graph_dfs.zig"
@@ -456,6 +456,78 @@ comments: true
} }
``` ```
=== "Kotlin"
```kotlin title="fractional_knapsack.kt"
/* 物品 */
class Item(
val w: Int, // 物品
val v: Int // 物品价值
)
/* 分数背包:贪心 */
fun fractionalKnapsack(
wgt: IntArray,
value: IntArray,
c: Int
): Double {
// 创建物品列表,包含两个属性:重量、价值
var cap = c
val items = arrayOfNulls<Item>(wgt.size)
for (i in wgt.indices) {
items[i] = Item(wgt[i], value[i])
}
// 按照单位价值 item.v / item.w 从高到低进行排序
Arrays.sort(items, Comparator.comparingDouble { item: Item -> -(item.v.toDouble() / item.w) })
// 循环贪心选择
var res = 0.0
for (item in items) {
if (item!!.w <= cap) {
// 若剩余容量充足,则将当前物品整个装进背包
res += item.v.toDouble()
cap -= item.w
} else {
// 若剩余容量不足,则将当前物品的一部分装进背包
res += item.v.toDouble() / item.w * cap
// 已无剩余容量,因此跳出循环
break
}
}
return res
}
/* 分数背包:贪心 */
fun fractionalKnapsack(
wgt: IntArray,
value: IntArray,
c: Int
): Double {
// 创建物品列表,包含两个属性:重量、价值
var cap = c
val items = arrayOfNulls<Item>(wgt.size)
for (i in wgt.indices) {
items[i] = Item(wgt[i], value[i])
}
// 按照单位价值 item.v / item.w 从高到低进行排序
Arrays.sort(items, Comparator.comparingDouble { item: Item -> -(item.v.toDouble() / item.w) })
// 循环贪心选择
var res = 0.0
for (item in items) {
if (item!!.w <= cap) {
// 若剩余容量充足,则将当前物品整个装进背包
res += item.v.toDouble()
cap -= item.w
} else {
// 若剩余容量不足,则将当前物品的一部分装进背包
res += item.v.toDouble() / item.w * cap
// 已无剩余容量,因此跳出循环
break
}
}
return res
}
```
=== "Zig" === "Zig"
```zig title="fractional_knapsack.zig" ```zig title="fractional_knapsack.zig"
+24
View File
@@ -283,6 +283,30 @@ comments: true
} }
``` ```
=== "Kotlin"
```kotlin title="coin_change_greedy.kt"
/* 零钱兑换:贪心 */
fun coinChangeGreedy(coins: IntArray, amt: Int): Int {
// 假设 coins 列表有序
var am = amt
var i = coins.size - 1
var count = 0
// 循环进行贪心选择,直到无剩余金额
while (am > 0) {
// 找到小于且最接近剩余金额的硬币
while (i > 0 && coins[i] > am) {
i--
}
// 选择 coins[i]
am -= coins[i]
count++
}
// 若未找到可行方案,则返回 -1
return if (am == 0) count else -1
}
```
=== "Zig" === "Zig"
```zig title="coin_change_greedy.zig" ```zig title="coin_change_greedy.zig"
@@ -368,6 +368,32 @@ $$
} }
``` ```
=== "Kotlin"
```kotlin title="max_capacity.kt"
/* 最大容量:贪心 */
fun maxCapacity(ht: IntArray): Int {
// 初始化 i, j,使其分列数组两端
var i = 0
var j = ht.size - 1
// 初始最大容量为 0
var res = 0
// 循环贪心选择,直至两板相遇
while (i < j) {
// 更新最大容量
val cap = (min(ht[i].toDouble(), ht[j].toDouble()) * (j - i)).toInt()
res = max(res.toDouble(), cap.toDouble()).toInt()
// 向内移动短板
if (ht[i] < ht[j]) {
i++
} else {
j--
}
}
return res
}
```
=== "Zig" === "Zig"
```zig title="max_capacity.zig" ```zig title="max_capacity.zig"
@@ -343,6 +343,31 @@ $$
} }
``` ```
=== "Kotlin"
```kotlin title="max_product_cutting.kt"
/* 最大切分乘积:贪心 */
fun maxProductCutting(n: Int): Int {
// 当 n <= 3 时,必须切分出一个 1
if (n <= 3) {
return 1 * (n - 1)
}
// 贪心地切分出 3 ,a 为 3 的个数,b 为余数
val a = n / 3
val b = n % 3
if (b == 1) {
// 当余数为 1 时,将一对 1 * 3 转化为 2 * 2
return 3.0.pow((a - 1).toDouble()).toInt() * 2 * 2
}
if (b == 2) {
// 当余数为 2 时,不做处理
return 3.0.pow(a.toDouble()).toInt() * 2 * 2
}
// 当余数为 0 时,不做处理
return 3.0.pow(a.toDouble()).toInt()
}
```
=== "Zig" === "Zig"
```zig title="max_product_cutting.zig" ```zig title="max_product_cutting.zig"
+46
View File
@@ -554,6 +554,46 @@ index = hash(key) % capacity
} }
``` ```
=== "Kotlin"
```kotlin title="simple_hash.kt"
/* 加法哈希 */
fun addHash(key: String): Int {
var hash = 0L
for (c in key.toCharArray()) {
hash = (hash + c.code) % MODULUS
}
return hash.toInt()
}
/* 乘法哈希 */
fun mulHash(key: String): Int {
var hash = 0L
for (c in key.toCharArray()) {
hash = (31 * hash + c.code) % MODULUS
}
return hash.toInt()
}
/* 异或哈希 */
fun xorHash(key: String): Int {
var hash = 0
for (c in key.toCharArray()) {
hash = hash xor c.code
}
return hash and MODULUS
}
/* 旋转哈希 */
fun rotHash(key: String): Int {
var hash = 0L
for (c in key.toCharArray()) {
hash = ((hash shl 4) xor (hash shr 28) xor c.code.toLong()) % MODULUS
}
return hash.toInt()
}
```
=== "Zig" === "Zig"
```zig title="simple_hash.zig" ```zig title="simple_hash.zig"
@@ -868,6 +908,12 @@ $$
// C 未提供内置 hash code 函数 // C 未提供内置 hash code 函数
``` ```
=== "Kotlin"
```kotlin title="built_in_hash.kt"
```
=== "Zig" === "Zig"
```zig title="built_in_hash.zig" ```zig title="built_in_hash.zig"
+241
View File
@@ -1311,6 +1311,121 @@ comments: true
} }
``` ```
=== "Kotlin"
```kotlin title="hash_map_chaining.kt"
/* 链式地址哈希表 */
class HashMapChaining() {
var size: Int // 键值对数量
var capacity: Int // 哈希表容量
val loadThres: Double // 触发扩容的负载因子阈值
val extendRatio: Int // 扩容倍数
var buckets: MutableList<MutableList<Pair>> // 桶数组
/* 构造方法 */
init {
size = 0
capacity = 4
loadThres = 2.0 / 3.0
extendRatio = 2
buckets = ArrayList(capacity)
for (i in 0..<capacity) {
buckets.add(mutableListOf())
}
}
/* 哈希函数 */
fun hashFunc(key: Int): Int {
return key % capacity
}
/* 负载因子 */
fun loadFactor(): Double {
return (size / capacity).toDouble()
}
/* 查询操作 */
fun get(key: Int): String? {
val index = hashFunc(key)
val bucket = buckets[index]
// 遍历桶,若找到 key ,则返回对应 val
for (pair in bucket) {
if (pair.key == key) return pair.value
}
// 若未找到 key ,则返回 null
return null
}
/* 添加操作 */
fun put(key: Int, value: String) {
// 当负载因子超过阈值时,执行扩容
if (loadFactor() > loadThres) {
extend()
}
val index = hashFunc(key)
val bucket = buckets[index]
// 遍历桶,若遇到指定 key ,则更新对应 val 并返回
for (pair in bucket) {
if (pair.key == key) {
pair.value = value
return
}
}
// 若无该 key ,则将键值对添加至尾部
val pair = Pair(key, value)
bucket.add(pair)
size++
}
/* 删除操作 */
fun remove(key: Int) {
val index = hashFunc(key)
val bucket = buckets[index]
// 遍历桶,从中删除键值对
for (pair in bucket) {
if (pair.key == key) {
bucket.remove(pair)
size--
break
}
}
}
/* 扩容哈希表 */
fun extend() {
// 暂存原哈希表
val bucketsTmp = buckets
// 初始化扩容后的新哈希表
capacity *= extendRatio
// mutablelist 无固定大小
buckets = mutableListOf()
for (i in 0..<capacity) {
buckets.add(mutableListOf())
}
size = 0
// 将键值对从原哈希表搬运至新哈希表
for (bucket in bucketsTmp) {
for (pair in bucket) {
put(pair.key, pair.value)
}
}
}
/* 打印哈希表 */
fun print() {
for (bucket in buckets) {
val res = mutableListOf<String>()
for (pair in bucket) {
val k = pair.key
val v = pair.value
res.add("$k -> $v")
}
println(res)
}
}
}
```
=== "Zig" === "Zig"
```zig title="hash_map_chaining.zig" ```zig title="hash_map_chaining.zig"
@@ -2831,6 +2946,132 @@ comments: true
} }
``` ```
=== "Kotlin"
```kotlin title="hash_map_open_addressing.kt"
/* 开放寻址哈希表 */
class HashMapOpenAddressing {
private var size: Int = 0 // 键值对数量
private var capacity = 4 // 哈希表容量
private val loadThres: Double = 2.0 / 3.0 // 触发扩容的负载因子阈值
private val extendRatio = 2 // 扩容倍数
private var buckets: Array<Pair?> // 桶数组
private val TOMBSTONE = Pair(-1, "-1") // 删除标记
/* 构造方法 */
init {
buckets = arrayOfNulls(capacity)
}
/* 哈希函数 */
fun hashFunc(key: Int): Int {
return key % capacity
}
/* 负载因子 */
fun loadFactor(): Double {
return (size / capacity).toDouble()
}
/* 搜索 key 对应的桶索引 */
fun findBucket(key: Int): Int {
var index = hashFunc(key)
var firstTombstone = -1
// 线性探测,当遇到空桶时跳出
while (buckets[index] != null) {
// 若遇到 key ,返回对应的桶索引
if (buckets[index]?.key == key) {
// 若之前遇到了删除标记,则将键值对移动至该索引处
if (firstTombstone != -1) {
buckets[firstTombstone] = buckets[index]
buckets[index] = TOMBSTONE
return firstTombstone // 返回移动后的桶索引
}
return index // 返回桶索引
}
// 记录遇到的首个删除标记
if (firstTombstone == -1 && buckets[index] == TOMBSTONE) {
firstTombstone = index
}
// 计算桶索引,越过尾部则返回头部
index = (index + 1) % capacity
}
// 若 key 不存在,则返回添加点的索引
return if (firstTombstone == -1) index else firstTombstone
}
/* 查询操作 */
fun get(key: Int): String? {
// 搜索 key 对应的桶索引
val index = findBucket(key)
// 若找到键值对,则返回对应 val
if (buckets[index] != null && buckets[index] != TOMBSTONE) {
return buckets[index]?.value
}
// 若键值对不存在,则返回 null
return null
}
/* 添加操作 */
fun put(key: Int, value: String) {
// 当负载因子超过阈值时,执行扩容
if (loadFactor() > loadThres) {
extend()
}
// 搜索 key 对应的桶索引
val index = findBucket(key)
// 若找到键值对,则覆盖 val 并返回
if (buckets[index] != null && buckets[index] != TOMBSTONE) {
buckets[index]!!.value = value
return
}
// 若键值对不存在,则添加该键值对
buckets[index] = Pair(key, value)
size++
}
/* 删除操作 */
fun remove(key: Int) {
// 搜索 key 对应的桶索引
val index = findBucket(key)
// 若找到键值对,则用删除标记覆盖它
if (buckets[index] != null && buckets[index] != TOMBSTONE) {
buckets[index] = TOMBSTONE
size--
}
}
/* 扩容哈希表 */
fun extend() {
// 暂存原哈希表
val bucketsTmp = buckets
// 初始化扩容后的新哈希表
capacity *= extendRatio
buckets = arrayOfNulls(capacity)
size = 0
// 将键值对从原哈希表搬运至新哈希表
for (pair in bucketsTmp) {
if (pair != null && pair != TOMBSTONE) {
put(pair.key, pair.value)
}
}
}
/* 打印哈希表 */
fun print() {
for (pair in buckets) {
if (pair == null) {
println("null")
} else if (pair == TOMBSTONE) {
println("TOMESTOME")
} else {
println("${pair.key} -> ${pair.value}")
}
}
}
}
```
=== "Zig" === "Zig"
```zig title="hash_map_open_addressing.zig" ```zig title="hash_map_open_addressing.zig"
+172
View File
@@ -277,6 +277,12 @@ comments: true
// C 未提供内置哈希表 // C 未提供内置哈希表
``` ```
=== "Kotlin"
```kotlin title="hash_map.kt"
```
=== "Zig" === "Zig"
```zig title="hash_map.zig" ```zig title="hash_map.zig"
@@ -473,6 +479,12 @@ comments: true
// C 未提供内置哈希表 // C 未提供内置哈希表
``` ```
=== "Kotlin"
```kotlin title="hash_map.kt"
```
=== "Zig" === "Zig"
```zig title="hash_map.zig" ```zig title="hash_map.zig"
@@ -1525,6 +1537,166 @@ index = hash(key) % capacity
} }
``` ```
=== "Kotlin"
```kotlin title="array_hash_map.kt"
/* 键值对 */
class Pair(
var key: Int,
var value: String
)
/* 基于数组实现的哈希表 */
class ArrayHashMap {
private val buckets = arrayOfNulls<Pair>(100)
init {
// 初始化数组,包含 100 个桶
for (i in 0..<100) {
buckets[i] = null
}
}
/* 哈希函数 */
fun hashFunc(key: Int): Int {
val index = key % 100
return index
}
/* 查询操作 */
fun get(key: Int): String? {
val index = hashFunc(key)
val pair = buckets[index] ?: return null
return pair.value
}
/* 添加操作 */
fun put(key: Int, value: String) {
val pair = Pair(key, value)
val index = hashFunc(key)
buckets[index] = pair
}
/* 删除操作 */
fun remove(key: Int) {
val index = hashFunc(key)
// 置为 null ,代表删除
buckets[index] = null
}
/* 获取所有键值对 */
fun pairSet(): MutableList<Pair> {
val pairSet = ArrayList<Pair>()
for (pair in buckets) {
if (pair != null) pairSet.add(pair)
}
return pairSet
}
/* 获取所有键 */
fun keySet(): MutableList<Int> {
val keySet = ArrayList<Int>()
for (pair in buckets) {
if (pair != null) keySet.add(pair.key)
}
return keySet
}
/* 获取所有值 */
fun valueSet(): MutableList<String> {
val valueSet = ArrayList<String>()
for (pair in buckets) {
pair?.let { valueSet.add(it.value) }
}
return valueSet
}
/* 打印哈希表 */
fun print() {
for (kv in pairSet()) {
val key = kv.key
val value = kv.value
println("${key}->${value}")
}
}
}
/* 基于数组实现的哈希表 */
class ArrayHashMap {
private val buckets = arrayOfNulls<Pair>(100)
init {
// 初始化数组,包含 100 个桶
for (i in 0..<100) {
buckets[i] = null
}
}
/* 哈希函数 */
fun hashFunc(key: Int): Int {
val index = key % 100
return index
}
/* 查询操作 */
fun get(key: Int): String? {
val index = hashFunc(key)
val pair = buckets[index] ?: return null
return pair.value
}
/* 添加操作 */
fun put(key: Int, value: String) {
val pair = Pair(key, value)
val index = hashFunc(key)
buckets[index] = pair
}
/* 删除操作 */
fun remove(key: Int) {
val index = hashFunc(key)
// 置为 null ,代表删除
buckets[index] = null
}
/* 获取所有键值对 */
fun pairSet(): MutableList<Pair> {
val pairSet = ArrayList<Pair>()
for (pair in buckets) {
if (pair != null) pairSet.add(pair)
}
return pairSet
}
/* 获取所有键 */
fun keySet(): MutableList<Int> {
val keySet = ArrayList<Int>()
for (pair in buckets) {
if (pair != null) keySet.add(pair.key)
}
return keySet
}
/* 获取所有值 */
fun valueSet(): MutableList<String> {
val valueSet = ArrayList<String>()
for (pair in buckets) {
pair?.let { valueSet.add(it.value) }
}
return valueSet
}
/* 打印哈希表 */
fun print() {
for (kv in pairSet()) {
val key = kv.key
val value = kv.value
println("${key}->${value}")
}
}
}
```
=== "Zig" === "Zig"
```zig title="array_hash_map.zig" ```zig title="array_hash_map.zig"
+120
View File
@@ -185,6 +185,126 @@ comments: true
} }
``` ```
=== "Kotlin"
```kotlin title="my_heap.kt"
/* 大顶堆 */
class MaxHeap(nums: List<Int>?) {
// 使用列表而非数组,这样无须考虑扩容问题
// 将列表元素原封不动添加进堆
private val maxHeap = ArrayList(nums!!)
/* 构造函数,根据输入列表建堆 */
init {
// 堆化除叶节点以外的其他所有节点
for (i in parent(size() - 1) downTo 0) {
siftDown(i)
}
}
/* 获取左子节点的索引 */
private fun left(i: Int): Int {
return 2 * i + 1
}
/* 获取右子节点的索引 */
private fun right(i: Int): Int {
return 2 * i + 2
}
/* 获取父节点的索引 */
private fun parent(i: Int): Int {
return (i - 1) / 2 // 向下整除
}
/* 交换元素 */
private fun swap(i: Int, j: Int) {
maxHeap[i] = maxHeap[j].also { maxHeap[j] = maxHeap[i] }
}
/* 获取堆大小 */
fun size(): Int {
return maxHeap.size
}
/* 判断堆是否为空 */
fun isEmpty(): Boolean {
/* 判断堆是否为空 */
return size() == 0
}
/* 访问堆顶元素 */
fun peek(): Int {
return maxHeap[0]
}
/* 元素入堆 */
fun push(value: Int) {
// 添加节点
maxHeap.add(value)
// 从底至顶堆化
siftUp(size() - 1)
}
/* 从节点 i 开始,从底至顶堆化 */
private fun siftUp(it: Int) {
// Kotlin的函数参数不可变,因此创建临时变量
var i = it
while (true) {
// 获取节点 i 的父节点
val p = parent(i)
// 当“越过根节点”或“节点无须修复”时,结束堆化
if (p < 0 || maxHeap[i] <= maxHeap[p]) break
// 交换两节点
swap(i, p)
// 循环向上堆化
i = p
}
}
/* 元素出堆 */
fun pop(): Int {
// 判空处理
if (isEmpty()) throw IndexOutOfBoundsException()
// 交换根节点与最右叶节点(交换首元素与尾元素)
swap(0, size() - 1)
// 删除节点
val value = maxHeap.removeAt(size() - 1)
// 从顶至底堆化
siftDown(0)
// 返回堆顶元素
return value
}
/* 从节点 i 开始,从顶至底堆化 */
private fun siftDown(it: Int) {
// Kotlin的函数参数不可变,因此创建临时变量
var i = it
while (true) {
// 判断节点 i, l, r 中值最大的节点,记为 ma
val l = left(i)
val r = right(i)
var ma = i
if (l < size() && maxHeap[l] > maxHeap[ma]) ma = l
if (r < size() && maxHeap[r] > maxHeap[ma]) ma = r
// 若节点 i 最大或索引 l, r 越界,则无须继续堆化,跳出
if (ma == i) break
// 交换两节点
swap(i, ma)
// 循环向下堆化
i = ma
}
}
/* 打印堆(二叉树) */
fun print() {
val queue = PriorityQueue { a: Int, b: Int -> b - a }
queue.addAll(maxHeap)
printHeap(queue)
}
}
```
=== "Zig" === "Zig"
```zig title="my_heap.zig" ```zig title="my_heap.zig"
+100
View File
@@ -375,6 +375,12 @@ comments: true
// C 未提供内置 Heap 类 // C 未提供内置 Heap 类
``` ```
=== "Kotlin"
```kotlin title="heap.kt"
```
=== "Zig" === "Zig"
```zig title="heap.zig" ```zig title="heap.zig"
@@ -611,6 +617,25 @@ comments: true
} }
``` ```
=== "Kotlin"
```kotlin title="my_heap.kt"
/* 获取左子节点的索引 */
fun left(i: Int): Int {
return 2 * i + 1
}
/* 获取右子节点的索引 */
fun right(i: Int): Int {
return 2 * i + 2
}
/* 获取父节点的索引 */
fun parent(i: Int): Int {
return (i - 1) / 2 // 向下整除
}
```
=== "Zig" === "Zig"
```zig title="my_heap.zig" ```zig title="my_heap.zig"
@@ -733,6 +758,15 @@ comments: true
} }
``` ```
=== "Kotlin"
```kotlin title="my_heap.kt"
/* 访问堆顶元素 */
fun peek(): Int {
return maxHeap[0]
}
```
=== "Zig" === "Zig"
```zig title="my_heap.zig" ```zig title="my_heap.zig"
@@ -1093,6 +1127,34 @@ comments: true
} }
``` ```
=== "Kotlin"
```kotlin title="my_heap.kt"
/* 元素入堆 */
fun push(value: Int) {
// 添加节点
maxHeap.add(value)
// 从底至顶堆化
siftUp(size() - 1)
}
/* 从节点 i 开始,从底至顶堆化 */
fun siftUp(it: Int) {
// Kotlin的函数参数不可变,因此创建临时变量
var i = it
while (true) {
// 获取节点 i 的父节点
val p = parent(i)
// 当“越过根节点”或“节点无须修复”时,结束堆化
if (p < 0 || maxHeap[i] <= maxHeap[p]) break
// 交换两节点
swap(i, p)
// 循环向上堆化
i = p
}
}
```
=== "Zig" === "Zig"
```zig title="my_heap.zig" ```zig title="my_heap.zig"
@@ -1603,6 +1665,44 @@ comments: true
} }
``` ```
=== "Kotlin"
```kotlin title="my_heap.kt"
/* 元素出堆 */
fun pop(): Int {
// 判空处理
if (isEmpty()) throw IndexOutOfBoundsException()
// 交换根节点与最右叶节点(交换首元素与尾元素)
swap(0, size() - 1)
// 删除节点
val value = maxHeap.removeAt(size() - 1)
// 从顶至底堆化
siftDown(0)
// 返回堆顶元素
return value
}
/* 从节点 i 开始,从顶至底堆化 */
fun siftDown(it: Int) {
// Kotlin的函数参数不可变,因此创建临时变量
var i = it
while (true) {
// 判断节点 i, l, r 中值最大的节点,记为 ma
val l = left(i)
val r = right(i)
var ma = i
if (l < size() && maxHeap[l] > maxHeap[ma]) ma = l
if (r < size() && maxHeap[r] > maxHeap[ma]) ma = r
// 若节点 i 最大或索引 l, r 越界,则无须继续堆化,跳出
if (ma == i) break
// 交换两节点
swap(i, ma)
// 循环向下堆化
i = ma
}
}
```
=== "Zig" === "Zig"
```zig title="my_heap.zig" ```zig title="my_heap.zig"
+23
View File
@@ -411,6 +411,29 @@ comments: true
} }
``` ```
=== "Kotlin"
```kotlin title="top_k.kt"
/* 基于堆查找数组中最大的 k 个元素 */
fun topKHeap(nums: IntArray, k: Int): Queue<Int> {
// 初始化小顶堆
val heap = PriorityQueue<Int>()
// 将数组的前 k 个元素入堆
for (i in 0..<k) {
heap.offer(nums[i])
}
// 从第 k+1 个元素开始,保持堆的长度为 k
for (i in k..<nums.size) {
// 若当前元素大于堆顶元素,则将堆顶元素出堆、当前元素入堆
if (nums[i] > heap.peek()) {
heap.poll()
heap.offer(nums[i])
}
}
return heap
}
```
=== "Zig" === "Zig"
```zig title="top_k.zig" ```zig title="top_k.zig"
+13
View File
@@ -160,6 +160,19 @@ comments: true
*/ */
``` ```
=== "Kotlin"
```kotlin title=""
/* 标题注释,用于标注函数、类、测试样例等 */
// 内容注释,用于详解代码
/**
* 多行
* 注释
*/
```
=== "Zig" === "Zig"
```zig title="" ```zig title=""
+46
View File
@@ -313,6 +313,29 @@ comments: true
} }
``` ```
=== "Kotlin"
```kotlin title="binary_search.kt"
/* 二分查找(双闭区间) */
fun binarySearch(nums: IntArray, target: Int): Int {
// 初始化双闭区间 [0, n-1] ,即 i, j 分别指向数组首元素、尾元素
var i = 0
var j = nums.size - 1
// 循环,当搜索区间为空时跳出(当 i > j 时为空)
while (i <= j) {
val m = i + (j - i) / 2 // 计算中点索引 m
if (nums[m] < target) // 此情况说明 target 在区间 [m+1, j] 中
i = m + 1
else if (nums[m] > target) // 此情况说明 target 在区间 [i, m-1] 中
j = m - 1
else // 找到目标元素,返回其索引
return m
}
// 未找到目标元素,返回 -1
return -1
}
```
=== "Zig" === "Zig"
```zig title="binary_search.zig" ```zig title="binary_search.zig"
@@ -612,6 +635,29 @@ comments: true
} }
``` ```
=== "Kotlin"
```kotlin title="binary_search.kt"
/* 二分查找(左闭右开区间) */
fun binarySearchLCRO(nums: IntArray, target: Int): Int {
// 初始化左闭右开区间 [0, n) ,即 i, j 分别指向数组首元素、尾元素+1
var i = 0
var j = nums.size
// 循环,当搜索区间为空时跳出(当 i = j 时为空)
while (i < j) {
val m = i + (j - i) / 2 // 计算中点索引 m
if (nums[m] < target) // 此情况说明 target 在区间 [m+1, j) 中
i = m + 1
else if (nums[m] > target) // 此情况说明 target 在区间 [i, m) 中
j = m
else // 找到目标元素,返回其索引
return m
}
// 未找到目标元素,返回 -1
return -1
}
```
=== "Zig" === "Zig"
```zig title="binary_search.zig" ```zig title="binary_search.zig"
@@ -193,6 +193,22 @@ comments: true
} }
``` ```
=== "Kotlin"
```kotlin title="binary_search_edge.kt"
/* 二分查找最左一个 target */
fun binarySearchLeftEdge(nums: IntArray, target: Int): Int {
// 等价于查找 target 的插入点
val i = binarySearchInsertion(nums, target)
// 未找到 target ,返回 -1
if (i == nums.size || nums[i] != target) {
return -1
}
// 找到 target ,返回索引 i
return i
}
```
=== "Zig" === "Zig"
```zig title="binary_search_edge.zig" ```zig title="binary_search_edge.zig"
@@ -418,6 +434,24 @@ comments: true
} }
``` ```
=== "Kotlin"
```kotlin title="binary_search_edge.kt"
/* 二分查找最右一个 target */
fun binarySearchRightEdge(nums: IntArray, target: Int): Int {
// 转化为查找最左一个 target + 1
val i = binarySearchInsertion(nums, target + 1)
// j 指向最右一个 target ,i 指向首个大于 target 的元素
val j = i - 1
// 未找到 target ,返回 -1
if (j == -1 || nums[j] != target) {
return -1
}
// 找到 target ,返回索引 j
return j
}
```
=== "Zig" === "Zig"
```zig title="binary_search_edge.zig" ```zig title="binary_search_edge.zig"
@@ -268,6 +268,28 @@ comments: true
} }
``` ```
=== "Kotlin"
```kotlin title="binary_search_insertion.kt"
/* 二分查找插入点(无重复元素) */
fun binarySearchInsertionSimple(nums: IntArray, target: Int): Int {
var i = 0
var j = nums.size - 1 // 初始化双闭区间 [0, n-1]
while (i <= j) {
val m = i + (j - i) / 2 // 计算中点索引 m
if (nums[m] < target) {
i = m + 1 // target 在区间 [m+1, j] 中
} else if (nums[m] > target) {
j = m - 1 // target 在区间 [i, m-1] 中
} else {
return m // 找到 target ,返回插入点 m
}
}
// 未找到 target ,返回插入点 i
return i
}
```
=== "Zig" === "Zig"
```zig title="binary_search_insertion.zig" ```zig title="binary_search_insertion.zig"
@@ -572,6 +594,28 @@ comments: true
} }
``` ```
=== "Kotlin"
```kotlin title="binary_search_insertion.kt"
/* 二分查找插入点(存在重复元素) */
fun binarySearchInsertion(nums: IntArray, target: Int): Int {
var i = 0
var j = nums.size - 1 // 初始化双闭区间 [0, n-1]
while (i <= j) {
val m = i + (j - i) / 2 // 计算中点索引 m
if (nums[m] < target) {
i = m + 1 // target 在区间 [m+1, j] 中
} else if (nums[m] > target) {
j = m - 1 // target 在区间 [i, m-1] 中
} else {
j = m - 1 // 首个小于 target 的元素在区间 [i, m-1] 中
}
}
// 返回插入点 i
return i
}
```
=== "Zig" === "Zig"
```zig title="binary_search_insertion.zig" ```zig title="binary_search_insertion.zig"
@@ -209,6 +209,22 @@ comments: true
} }
``` ```
=== "Kotlin"
```kotlin title="two_sum.kt"
/* 方法一:暴力枚举 */
fun twoSumBruteForce(nums: IntArray, target: Int): IntArray {
val size = nums.size
// 两层循环,时间复杂度为 O(n^2)
for (i in 0..<size - 1) {
for (j in i + 1..<size) {
if (nums[i] + nums[j] == target) return intArrayOf(i, j)
}
}
return IntArray(0)
}
```
=== "Zig" === "Zig"
```zig title="two_sum.zig" ```zig title="two_sum.zig"
@@ -487,6 +503,25 @@ comments: true
} }
``` ```
=== "Kotlin"
```kotlin title="two_sum.kt"
/* 方法二:辅助哈希表 */
fun twoSumHashTable(nums: IntArray, target: Int): IntArray {
val size = nums.size
// 辅助哈希表,空间复杂度为 O(n)
val dic = HashMap<Int, Int>()
// 单层循环,时间复杂度为 O(n)
for (i in 0..<size) {
if (dic.containsKey(target - nums[i])) {
return intArrayOf(dic[target - nums[i]]!!, i)
}
dic[nums[i]] = i
}
return IntArray(0)
}
```
=== "Zig" === "Zig"
```zig title="two_sum.zig" ```zig title="two_sum.zig"
+39
View File
@@ -253,6 +253,24 @@ comments: true
} }
``` ```
=== "Kotlin"
```kotlin title="bubble_sort.kt"
/* 冒泡排序 */
fun bubbleSort(nums: IntArray) {
// 外循环:未排序区间为 [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] }
}
}
}
}
```
=== "Zig" === "Zig"
```zig title="bubble_sort.zig" ```zig title="bubble_sort.zig"
@@ -535,6 +553,27 @@ comments: true
} }
``` ```
=== "Kotlin"
```kotlin title="bubble_sort.kt"
/* 冒泡排序(标志优化) */
fun bubbleSortWithFlag(nums: IntArray) {
// 外循环:未排序区间为 [0, i]
for (i in nums.size - 1 downTo 1) {
var flag = false // 初始化标志位
// 内循环:将未排序区间 [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] = nums[j + 1] }
flag = true // 记录交换元素
}
}
if (!flag) break // 此轮“冒泡”未交换任何元素,直接跳出
}
}
```
=== "Zig" === "Zig"
```zig title="bubble_sort.zig" ```zig title="bubble_sort.zig"
+33
View File
@@ -388,6 +388,39 @@ comments: true
} }
``` ```
=== "Kotlin"
```kotlin title="bucket_sort.kt"
/* 桶排序 */
fun bucketSort(nums: FloatArray) {
// 初始化 k = n/2 个桶,预期向每个桶分配 2 个元素
val k = nums.size / 2
val buckets = ArrayList<ArrayList<Float>>()
for (i in 0..<k) {
buckets.add(ArrayList())
}
// 1. 将数组元素分配到各个桶中
for (num in nums) {
// 输入数据范围为 [0, 1),使用 num * k 映射到索引范围 [0, k-1]
val i = (num * k).toInt()
// 将 num 添加进桶 i
buckets[i].add(num)
}
// 2. 对各个桶执行排序
for (bucket in buckets) {
// 使用内置排序函数,也可以替换成其他排序算法
bucket.sort()
}
// 3. 遍历桶合并结果
var i = 0
for (bucket in buckets) {
for (num in bucket) {
nums[i++] = num
}
}
}
```
=== "Zig" === "Zig"
```zig title="bucket_sort.zig" ```zig title="bucket_sort.zig"
+68
View File
@@ -315,6 +315,36 @@ comments: true
} }
``` ```
=== "Kotlin"
```kotlin title="counting_sort.kt"
/* 计数排序 */
// 简单实现,无法用于排序对象
fun countingSortNaive(nums: IntArray) {
// 1. 统计数组最大元素 m
var m = 0
for (num in nums) {
m = max(m.toDouble(), num.toDouble()).toInt()
}
// 2. 统计各数字的出现次数
// counter[num] 代表 num 的出现次数
val counter = IntArray(m + 1)
for (num in nums) {
counter[num]++
}
// 3. 遍历 counter ,将各元素填入原数组 nums
var i = 0
for (num in 0..<m + 1) {
var j = 0
while (j < counter[num]) {
nums[i] = num
j++
i++
}
}
}
```
=== "Zig" === "Zig"
```zig title="counting_sort.zig" ```zig title="counting_sort.zig"
@@ -777,6 +807,44 @@ $$
} }
``` ```
=== "Kotlin"
```kotlin title="counting_sort.kt"
/* 计数排序 */
// 完整实现,可排序对象,并且是稳定排序
fun countingSort(nums: IntArray) {
// 1. 统计数组最大元素 m
var m = 0
for (num in nums) {
m = max(m.toDouble(), num.toDouble()).toInt()
}
// 2. 统计各数字的出现次数
// counter[num] 代表 num 的出现次数
val counter = IntArray(m + 1)
for (num in nums) {
counter[num]++
}
// 3. 求 counter 的前缀和,将“出现次数”转换为“尾索引”
// 即 counter[num]-1 是 num 在 res 中最后一次出现的索引
for (i in 0..<m) {
counter[i + 1] += counter[i]
}
// 4. 倒序遍历 nums ,将各元素填入结果数组 res
// 初始化数组 res 用于记录结果
val n = nums.size
val res = IntArray(n)
for (i in n - 1 downTo 0) {
val num = nums[i]
res[counter[num] - 1] = num // 将 num 放置到对应索引处
counter[num]-- // 令前缀和自减 1 ,得到下次放置 num 的索引
}
// 使用结果数组 res 覆盖原数组 nums
for (i in 0..<n) {
nums[i] = res[i]
}
}
```
=== "Zig" === "Zig"
```zig title="counting_sort.zig" ```zig title="counting_sort.zig"
+38
View File
@@ -534,6 +534,44 @@ comments: true
} }
``` ```
=== "Kotlin"
```kotlin title="heap_sort.kt"
/* 堆的长度为 n ,从节点 i 开始,从顶至底堆化 */
fun siftDown(nums: IntArray, n: Int, li: Int) {
var i = li
while (true) {
// 判断节点 i, l, r 中值最大的节点,记为 ma
val l = 2 * i + 1
val r = 2 * i + 2
var ma = i
if (l < n && nums[l] > nums[ma]) ma = l
if (r < n && nums[r] > nums[ma]) ma = r
// 若节点 i 最大或索引 l, r 越界,则无须继续堆化,跳出
if (ma == i) break
// 交换两节点
nums[i] = nums[ma].also { nums[ma] = nums[i] }
// 循环向下堆化
i = ma
}
}
/* 堆排序 */
fun heapSort(nums: IntArray) {
// 建堆操作:堆化除叶节点以外的其他所有节点
for (i in nums.size / 2 - 1 downTo 0) {
siftDown(nums, nums.size, i)
}
// 从堆中提取最大元素,循环 n-1 轮
for (i in nums.size - 1 downTo 1) {
// 交换根节点与最右叶节点(交换首元素与尾元素)
nums[0] = nums[i].also { nums[i] = nums[0] }
// 以根节点为起点,从顶至底进行堆化
siftDown(nums, i, 0)
}
}
```
=== "Zig" === "Zig"
```zig title="heap_sort.zig" ```zig title="heap_sort.zig"
+19
View File
@@ -231,6 +231,25 @@ comments: true
} }
``` ```
=== "Kotlin"
```kotlin title="insertion_sort.kt"
/* 插入排序 */
fun insertionSort(nums: IntArray) {
//外循环: 已排序元素为 1, 2, ..., n
for (i in nums.indices) {
val base = nums[i]
var j = i - 1
// 内循环: 将 base 插入到已排序部分的正确位置
while (j >= 0 && nums[j] > base) {
nums[j + 1] = nums[j] // 将 nums[j] 向右移动一位
j--
}
nums[j + 1] = base // 将 base 赋值到正确位置
}
}
```
=== "Zig" === "Zig"
```zig title="insertion_sort.zig" ```zig title="insertion_sort.zig"
+43
View File
@@ -582,6 +582,49 @@ comments: true
} }
``` ```
=== "Kotlin"
```kotlin title="merge_sort.kt"
/* 合并左子数组和右子数组 */
fun merge(nums: IntArray, left: Int, mid: Int, right: Int) {
// 左子数组区间为 [left, mid], 右子数组区间为 [mid+1, right]
// 创建一个临时数组 tmp ,用于存放合并后的结果
val tmp = IntArray(right - left + 1)
// 初始化左子数组和右子数组的起始索引
var i = left
var j = mid + 1
var k = 0
// 当左右子数组都还有元素时,进行比较并将较小的元素复制到临时数组中
while (i <= mid && j <= right) {
if (nums[i] <= nums[j]) tmp[k++] = nums[i++]
else tmp[k++] = nums[j++]
}
// 将左子数组和右子数组的剩余元素复制到临时数组中
while (i <= mid) {
tmp[k++] = nums[i++]
}
while (j <= right) {
tmp[k++] = nums[j++]
}
// 将临时数组 tmp 中的元素复制回原数组 nums 的对应区间
for (l in tmp.indices) {
nums[left + l] = tmp[l]
}
}
/* 归并排序 */
fun mergeSort(nums: IntArray, left: Int, right: Int) {
// 终止条件
if (left >= right) return // 当子数组长度为 1 时终止递归
// 划分阶段
val mid = (left + right) / 2 // 计算中点
mergeSort(nums, left, mid) // 递归左子数组
mergeSort(nums, mid + 1, right) // 递归右子数组
// 合并阶段
merge(nums, left, mid, right)
}
```
=== "Zig" === "Zig"
```zig title="merge_sort.zig" ```zig title="merge_sort.zig"
+87
View File
@@ -326,6 +326,31 @@ comments: true
} }
``` ```
=== "Kotlin"
```kotlin title="quick_sort.kt"
/* 元素交换 */
fun swap(nums: IntArray, i: Int, j: Int) {
nums[i] = nums[j].also { nums[j] = nums[i] }
}
/* 哨兵划分 */
fun partition(nums: IntArray, left: Int, right: Int): Int {
// 以 nums[left] 为基准数
var i = left
var j = right
while (i < j) {
while (i < j && nums[j] >= nums[left])
j-- // 从右向左找首个小于基准数的元素
while (i < j && nums[i] <= nums[left])
i++ // 从左向右找首个大于基准数的元素
swap(nums, i, j) // 交换这两个元素
}
swap(nums, i, left) // 将基准数交换至两子数组的分界线
return i // 返回基准数的索引
}
```
=== "Zig" === "Zig"
```zig title="quick_sort.zig" ```zig title="quick_sort.zig"
@@ -569,6 +594,21 @@ comments: true
} }
``` ```
=== "Kotlin"
```kotlin title="quick_sort.kt"
/* 快速排序 */
fun quickSort(nums: IntArray, left: Int, right: Int) {
// 子数组长度为 1 时终止递归
if (left >= right) return
// 哨兵划分
val pivot = partition(nums, left, right)
// 递归左子数组、右子数组
quickSort(nums, left, pivot - 1)
quickSort(nums, pivot + 1, right)
}
```
=== "Zig" === "Zig"
```zig title="quick_sort.zig" ```zig title="quick_sort.zig"
@@ -1001,6 +1041,38 @@ comments: true
} }
``` ```
=== "Kotlin"
```kotlin title="quick_sort.kt"
/* 选取三个候选元素的中位数 */
fun medianThree(nums: IntArray, left: Int, mid: Int, right: Int): Int {
val l = nums[left]
val m = nums[mid]
val r = nums[right]
if ((m in l..r) || (m in r..l))
return mid // m 在 l 和 r 之间
if ((l in m..r) || (l in r..m))
return left // l 在 m 和 r 之间
return right
}
/* 哨兵划分 */
fun partition(nums: IntArray, left: Int, right: Int): Int {
// 以 nums[left] 为基准数
var i = left
var j = right
while (i < j) {
while (i < j && nums[j] >= nums[left])
j-- // 从右向左找首个小于基准数的元素
while (i < j && nums[i] <= nums[left])
i++ // 从左向右找首个大于基准数的元素
swap(nums, i, j) // 交换这两个元素
}
swap(nums, i, left) // 将基准数交换至两子数组的分界线
return i // 返回基准数的索引
}
```
=== "Zig" === "Zig"
```zig title="quick_sort.zig" ```zig title="quick_sort.zig"
@@ -1277,6 +1349,21 @@ comments: true
} }
``` ```
=== "Kotlin"
```kotlin title="quick_sort.kt"
/* 快速排序 */
fun quickSort(nums: IntArray, left: Int, right: Int) {
// 子数组长度为 1 时终止递归
if (left >= right) return
// 哨兵划分
val pivot = partition(nums, left, right)
// 递归左子数组、右子数组
quickSort(nums, left, pivot - 1)
quickSort(nums, pivot + 1, right)
}
```
=== "Zig" === "Zig"
```zig title="quick_sort.zig" ```zig title="quick_sort.zig"
+53
View File
@@ -619,6 +619,59 @@ $$
} }
``` ```
=== "Kotlin"
```kotlin title="radix_sort.kt"
/* 获取元素 num 的第 k 位,其中 exp = 10^(k-1) */
fun digit(num: Int, exp: Int): Int {
// 传入 exp 而非 k 可以避免在此重复执行昂贵的次方计算
return (num / exp) % 10
}
/* 计数排序(根据 nums 第 k 位排序) */
fun countingSortDigit(nums: IntArray, exp: Int) {
// 十进制的位范围为 0~9 ,因此需要长度为 10 的桶数组
val counter = IntArray(10)
val n = nums.size
// 统计 0~9 各数字的出现次数
for (i in 0..<n) {
val d = digit(nums[i], exp) // 获取 nums[i] 第 k 位,记为 d
counter[d]++ // 统计数字 d 的出现次数
}
// 求前缀和,将“出现个数”转换为“数组索引”
for (i in 1..9) {
counter[i] += counter[i - 1]
}
// 倒序遍历,根据桶内统计结果,将各元素填入 res
val res = IntArray(n)
for (i in n - 1 downTo 0) {
val d = digit(nums[i], exp)
val j = counter[d] - 1 // 获取 d 在数组中的索引 j
res[j] = nums[i] // 将当前元素填入索引 j
counter[d]-- // 将 d 的数量减 1
}
// 使用结果覆盖原数组 nums
for (i in 0..<n) nums[i] = res[i]
}
/* 基数排序 */
fun radixSort(nums: IntArray) {
// 获取数组的最大元素,用于判断最大位数
var m = Int.MIN_VALUE
for (num in nums) if (num > m) m = num
var exp = 1
// 按照从低位到高位的顺序遍历
while (exp <= m) {
// 对数组元素的第 k 位执行计数排序
// k = 1 -> exp = 1
// k = 2 -> exp = 10
// 即 exp = 10^(k-1)
countingSortDigit(nums, exp)
exp *= 10
}
}
```
=== "Zig" === "Zig"
```zig title="radix_sort.zig" ```zig title="radix_sort.zig"
+19
View File
@@ -281,6 +281,25 @@ comments: true
} }
``` ```
=== "Kotlin"
```kotlin title="selection_sort.kt"
/* 选择排序 */
fun selectionSort(nums: IntArray) {
val n = nums.size
// 外循环:未排序区间为 [i, n-1]
for (i in 0..<n - 1) {
var k = i
// 内循环:找到未排序区间内的最小元素
for (j in i + 1..<n) {
if (nums[j] < nums[k]) k = j // 记录最小元素的索引
}
// 将该最小元素与未排序区间的首个元素交换
nums[i] = nums[k].also { nums[k] = nums[i] }
}
}
```
=== "Zig" === "Zig"
```zig title="selection_sort.zig" ```zig title="selection_sort.zig"
+238
View File
@@ -334,6 +334,12 @@ comments: true
// C 未提供内置双向队列 // C 未提供内置双向队列
``` ```
=== "Kotlin"
```kotlin title="deque.kt"
```
=== "Zig" === "Zig"
```zig title="deque.zig" ```zig title="deque.zig"
@@ -1836,6 +1842,133 @@ comments: true
} }
``` ```
=== "Kotlin"
```kotlin title="linkedlist_deque.kt"
/* 双向链表节点 */
class ListNode(var value: Int) {
// 节点值
var next: ListNode? = null // 后继节点引用
var prev: ListNode? = null // 前驱节点引用
}
/* 基于双向链表实现的双向队列 */
class LinkedListDeque {
private var front: ListNode? = null // 头节点 front ,尾节点 rear
private var rear: ListNode? = null
private var queSize = 0 // 双向队列的长度
/* 获取双向队列的长度 */
fun size(): Int {
return queSize
}
/* 判断双向队列是否为空 */
fun isEmpty(): Boolean {
return size() == 0
}
/* 入队操作 */
fun push(num: Int, isFront: Boolean) {
val node = ListNode(num)
// 若链表为空,则令 front 和 rear 都指向 node
if (isEmpty()) {
rear = node
front = rear
// 队首入队操作
} else if (isFront) {
// 将 node 添加至链表头部
front?.prev = node
node.next = front
front = node // 更新头节点
// 队尾入队操作
} else {
// 将 node 添加至链表尾部
rear?.next = node
node.prev = rear
rear = node // 更新尾节点
}
queSize++ // 更新队列长度
}
/* 队首入队 */
fun pushFirst(num: Int) {
push(num, true)
}
/* 队尾入队 */
fun pushLast(num: Int) {
push(num, false)
}
/* 出队操作 */
fun pop(isFront: Boolean): Int {
if (isEmpty()) throw IndexOutOfBoundsException()
val value: Int
// 队首出队操作
if (isFront) {
value = front!!.value // 暂存头节点值
// 删除头节点
val fNext = front!!.next
if (fNext != null) {
fNext.prev = null
front!!.next = null
}
front = fNext // 更新头节点
// 队尾出队操作
} else {
value = rear!!.value // 暂存尾节点值
// 删除尾节点
val rPrev = rear!!.prev
if (rPrev != null) {
rPrev.next = null
rear!!.prev = null
}
rear = rPrev // 更新尾节点
}
queSize-- // 更新队列长度
return value
}
/* 队首出队 */
fun popFirst(): Int {
return pop(true)
}
/* 队尾出队 */
fun popLast(): Int {
return pop(false)
}
/* 访问队首元素 */
fun peekFirst(): Int {
if (isEmpty()) {
throw IndexOutOfBoundsException()
}
return front!!.value
}
/* 访问队尾元素 */
fun peekLast(): Int {
if (isEmpty()) throw IndexOutOfBoundsException()
return rear!!.value
}
/* 返回数组用于打印 */
fun toArray(): IntArray {
var node = front
val res = IntArray(size())
for (i in res.indices) {
res[i] = node!!.value
node = node.next
}
return res
}
}
```
=== "Zig" === "Zig"
```zig title="linkedlist_deque.zig" ```zig title="linkedlist_deque.zig"
@@ -3213,6 +3346,111 @@ comments: true
} }
``` ```
=== "Kotlin"
```kotlin title="array_deque.kt"
/* 基于环形数组实现的双向队列 */
class ArrayDeque(capacity: Int) {
private var nums = IntArray(capacity) // 用于存储双向队列元素的数组
private var front = 0 // 队首指针,指向队首元素
private var queSize = 0 // 双向队列长度
/* 获取双向队列的容量 */
fun capacity(): Int {
return nums.size
}
/* 获取双向队列的长度 */
fun size(): Int {
return queSize
}
/* 判断双向队列是否为空 */
fun isEmpty(): Boolean {
return queSize == 0
}
/* 计算环形数组索引 */
private fun index(i: Int): Int {
// 通过取余操作实现数组首尾相连
// 当 i 越过数组尾部后,回到头部
// 当 i 越过数组头部后,回到尾部
return (i + capacity()) % capacity()
}
/* 队首入队 */
fun pushFirst(num: Int) {
if (queSize == capacity()) {
println("双向队列已满")
return
}
// 队首指针向左移动一位
// 通过取余操作实现 front 越过数组头部后回到尾部
front = index(front - 1)
// 将 num 添加至队首
nums[front] = num
queSize++
}
/* 队尾入队 */
fun pushLast(num: Int) {
if (queSize == capacity()) {
println("双向队列已满")
return
}
// 计算队尾指针,指向队尾索引 + 1
val rear = index(front + queSize)
// 将 num 添加至队尾
nums[rear] = num
queSize++
}
/* 队首出队 */
fun popFirst(): Int {
val num = peekFirst()
// 队首指针向后移动一位
front = index(front + 1)
queSize--
return num
}
/* 访问队尾元素 */
fun popLast(): Int {
val num = peekLast()
queSize--
return num
}
/* 访问队首元素 */
fun peekFirst(): Int {
if (isEmpty()) throw IndexOutOfBoundsException()
return nums[front]
}
/* 访问队尾元素 */
fun peekLast(): Int {
if (isEmpty()) throw IndexOutOfBoundsException()
// 计算尾元素索引
val last = index(front + queSize - 1)
return nums[last]
}
/* 返回数组用于打印 */
fun toArray(): IntArray {
// 仅转换有效长度范围内的列表元素
val res = IntArray(queSize)
var i = 0
var j = front
while (i < queSize) {
res[i] = nums[index(j)]
i++
j++
}
return res
}
}
```
=== "Zig" === "Zig"
```zig title="array_deque.zig" ```zig title="array_deque.zig"
+140
View File
@@ -312,6 +312,12 @@ comments: true
// C 未提供内置队列 // C 未提供内置队列
``` ```
=== "Kotlin"
```kotlin title="queue.kt"
```
=== "Zig" === "Zig"
```zig title="queue.zig" ```zig title="queue.zig"
@@ -1125,6 +1131,71 @@ comments: true
} }
``` ```
=== "Kotlin"
```kotlin title="linkedlist_queue.kt"
/* 基于链表实现的队列 */
class LinkedListQueue(
// 头节点 front ,尾节点 rear
private var front: ListNode? = null,
private var rear: ListNode? = null,
private var queSize: Int = 0
) {
/* 获取队列的长度 */
fun size(): Int {
return queSize
}
/* 判断队列是否为空 */
fun isEmpty(): Boolean {
return size() == 0
}
/* 入队 */
fun push(num: Int) {
// 在尾节点后添加 num
val node = ListNode(num)
// 如果队列为空,则令头、尾节点都指向该节点
if (front == null) {
front = node
rear = node
// 如果队列不为空,则将该节点添加到尾节点后
} else {
rear?.next = node
rear = node
}
queSize++
}
/* 出队 */
fun pop(): Int {
val num = peek()
// 删除头节点
front = front?.next
queSize--
return num
}
/* 访问队首元素 */
fun peek(): Int {
if (isEmpty()) throw IndexOutOfBoundsException()
return front!!.value
}
/* 将链表转化为 Array 并返回 */
fun toArray(): IntArray {
var node = front
val res = IntArray(size())
for (i in res.indices) {
res[i] = node!!.value
node = node.next
}
return res
}
}
```
=== "Zig" === "Zig"
```zig title="linkedlist_queue.zig" ```zig title="linkedlist_queue.zig"
@@ -2036,6 +2107,75 @@ comments: true
} }
``` ```
=== "Kotlin"
```kotlin title="array_queue.kt"
/* 基于环形数组实现的队列 */
class ArrayQueue(capacity: Int) {
private val nums = IntArray(capacity) // 用于存储队列元素的数组
private var front = 0 // 队首指针,指向队首元素
private var queSize = 0 // 队列长度
/* 获取队列的容量 */
fun capacity(): Int {
return nums.size
}
/* 获取队列的长度 */
fun size(): Int {
return queSize
}
/* 判断队列是否为空 */
fun isEmpty(): Boolean {
return queSize == 0
}
/* 入队 */
fun push(num: Int) {
if (queSize == capacity()) {
println("队列已满")
return
}
// 计算队尾指针,指向队尾索引 + 1
// 通过取余操作实现 rear 越过数组尾部后回到头部
val rear = (front + queSize) % capacity()
// 将 num 添加至队尾
nums[rear] = num
queSize++
}
/* 出队 */
fun pop(): Int {
val num = peek()
// 队首指针向后移动一位,若越过尾部,则返回到数组头部
front = (front + 1) % capacity()
queSize--
return num
}
/* 访问队首元素 */
fun peek(): Int {
if (isEmpty()) throw IndexOutOfBoundsException()
return nums[front]
}
/* 返回数组 */
fun toArray(): IntArray {
// 仅转换有效长度范围内的列表元素
val res = IntArray(queSize)
var i = 0
var j = front
while (i < queSize) {
res[i] = nums[j % capacity()]
i++
j++
}
return res
}
}
```
=== "Zig" === "Zig"
```zig title="array_queue.zig" ```zig title="array_queue.zig"
+102
View File
@@ -306,6 +306,12 @@ comments: true
// C 未提供内置栈 // C 未提供内置栈
``` ```
=== "Kotlin"
```kotlin title="stack.kt"
```
=== "Zig" === "Zig"
```zig title="stack.zig" ```zig title="stack.zig"
@@ -1008,6 +1014,60 @@ comments: true
} }
``` ```
=== "Kotlin"
```kotlin title="linkedlist_stack.kt"
/* 基于链表实现的栈 */
class LinkedListStack(
private var stackPeek: ListNode? = null, // 将头节点作为栈顶
private var stkSize: Int = 0 // 栈的长度
) {
/* 获取栈的长度 */
fun size(): Int {
return stkSize
}
/* 判断栈是否为空 */
fun isEmpty(): Boolean {
return size() == 0
}
/* 入栈 */
fun push(num: Int) {
val node = ListNode(num)
node.next = stackPeek
stackPeek = node
stkSize++
}
/* 出栈 */
fun pop(): Int? {
val num = peek()
stackPeek = stackPeek?.next
stkSize--;
return num
}
/* 访问栈顶元素 */
fun peek(): Int? {
if (isEmpty()) throw IndexOutOfBoundsException()
return stackPeek?.value
}
/* 将 List 转化为 Array 并返回 */
fun toArray(): IntArray {
var node = stackPeek
val res = IntArray(size())
for (i in res.size - 1 downTo 0) {
res[i] = node?.value!!
node = node.next
}
return res
}
}
```
=== "Zig" === "Zig"
```zig title="linkedlist_stack.zig" ```zig title="linkedlist_stack.zig"
@@ -1643,6 +1703,48 @@ comments: true
} }
``` ```
=== "Kotlin"
```kotlin title="array_stack.kt"
/* 基于数组实现的栈 */
class ArrayStack {
// 初始化列表(动态数组)
private val stack = ArrayList<Int>()
/* 获取栈的长度 */
fun size(): Int {
return stack.size
}
/* 判断栈是否为空 */
fun isEmpty(): Boolean {
return size() == 0
}
/* 入栈 */
fun push(num: Int) {
stack.add(num)
}
/* 出栈 */
fun pop(): Int {
if (isEmpty()) throw IndexOutOfBoundsException()
return stack.removeAt(size() - 1)
}
/* 访问栈顶元素 */
fun peek(): Int {
if (isEmpty()) throw IndexOutOfBoundsException()
return stack[size() - 1]
}
/* 将 List 转化为 Array 并返回 */
fun toArray(): Array<Any> {
return stack.toArray()
}
}
```
=== "Zig" === "Zig"
```zig title="array_stack.zig" ```zig title="array_stack.zig"
@@ -120,6 +120,12 @@ comments: true
int tree[] = {1, 2, 3, 4, INT_MAX, 6, 7, 8, 9, INT_MAX, INT_MAX, 12, INT_MAX, INT_MAX, 15}; int tree[] = {1, 2, 3, 4, INT_MAX, 6, 7, 8, 9, INT_MAX, INT_MAX, 12, INT_MAX, INT_MAX, 15};
``` ```
=== "Kotlin"
```kotlin title=""
```
=== "Zig" === "Zig"
```zig title="" ```zig title=""
@@ -1155,6 +1161,85 @@ comments: true
} }
``` ```
=== "Kotlin"
```kotlin title="array_binary_tree.kt"
/* 数组表示下的二叉树类 */
class ArrayBinaryTree(val tree: List<Int?>) {
/* 列表容量 */
fun size(): Int {
return tree.size
}
/* 获取索引为 i 节点的值 */
fun value(i: Int): Int? {
// 若索引越界,则返回 null ,代表空位
if (i < 0 || i >= size()) return null
return tree[i]
}
/* 获取索引为 i 节点的左子节点的索引 */
fun left(i: Int): Int {
return 2 * i + 1
}
/* 获取索引为 i 节点的右子节点的索引 */
fun right(i: Int): Int {
return 2 * i + 2
}
/* 获取索引为 i 节点的父节点的索引 */
fun parent(i: Int): Int {
return (i - 1) / 2
}
/* 层序遍历 */
fun levelOrder(): List<Int?> {
val res = ArrayList<Int?>()
// 直接遍历数组
for (i in 0..<size()) {
if (value(i) != null) res.add(value(i))
}
return res
}
/* 深度优先遍历 */
fun dfs(i: Int, order: String, res: MutableList<Int?>) {
// 若为空位,则返回
if (value(i) == null) return
// 前序遍历
if ("pre" == order) res.add(value(i))
dfs(left(i), order, res)
// 中序遍历
if ("in" == order) res.add(value(i))
dfs(right(i), order, res)
// 后序遍历
if ("post" == order) res.add(value(i))
}
/* 前序遍历 */
fun preOrder(): List<Int?> {
val res = ArrayList<Int?>()
dfs(0, "pre", res)
return res
}
/* 中序遍历 */
fun inOrder(): List<Int?> {
val res = ArrayList<Int?>()
dfs(0, "in", res)
return res
}
/* 后序遍历 */
fun postOrder(): List<Int?> {
val res = ArrayList<Int?>()
dfs(0, "post", res)
return res
}
}
```
=== "Zig" === "Zig"
```zig title="array_binary_tree.zig" ```zig title="array_binary_tree.zig"
+168
View File
@@ -208,6 +208,12 @@ AVL 树既是二叉搜索树,也是平衡二叉树,同时满足这两类二
} }
``` ```
=== "Kotlin"
```kotlin title=""
```
=== "Zig" === "Zig"
```zig title="" ```zig title=""
@@ -419,6 +425,22 @@ AVL 树既是二叉搜索树,也是平衡二叉树,同时满足这两类二
} }
``` ```
=== "Kotlin"
```kotlin title="avl_tree.kt"
/* 获取节点高度 */
fun height(node: TreeNode?): Int {
// 空节点高度为 -1 ,叶节点高度为 0
return node?.height ?: -1
}
/* 更新节点高度 */
fun updateHeight(node: TreeNode?) {
// 节点高度等于最高子树高度 + 1
node?.height = (max(height(node?.left).toDouble(), height(node?.right).toDouble()) + 1).toInt()
}
```
=== "Zig" === "Zig"
```zig title="avl_tree.zig" ```zig title="avl_tree.zig"
@@ -582,6 +604,18 @@ AVL 树既是二叉搜索树,也是平衡二叉树,同时满足这两类二
} }
``` ```
=== "Kotlin"
```kotlin title="avl_tree.kt"
/* 获取平衡因子 */
fun balanceFactor(node: TreeNode?): Int {
// 空节点平衡因子为 0
if (node == null) return 0
// 节点平衡因子 = 左子树高度 - 右子树高度
return height(node.left) - height(node.right)
}
```
=== "Zig" === "Zig"
```zig title="avl_tree.zig" ```zig title="avl_tree.zig"
@@ -833,6 +867,24 @@ AVL 树的特点在于“旋转”操作,它能够在不影响二叉树的中
} }
``` ```
=== "Kotlin"
```kotlin title="avl_tree.kt"
/* 右旋操作 */
fun rightRotate(node: TreeNode?): TreeNode {
val child = node!!.left
val grandChild = child!!.right
// 以 child 为原点,将 node 向右旋转
child.right = node
node.left = grandChild
// 更新节点高度
updateHeight(node)
updateHeight(child)
// 返回旋转后子树的根节点
return child
}
```
=== "Zig" === "Zig"
```zig title="avl_tree.zig" ```zig title="avl_tree.zig"
@@ -1070,6 +1122,24 @@ AVL 树的特点在于“旋转”操作,它能够在不影响二叉树的中
} }
``` ```
=== "Kotlin"
```kotlin title="avl_tree.kt"
/* 左旋操作 */
fun leftRotate(node: TreeNode?): TreeNode {
val child = node!!.right
val grandChild = child!!.left
// 以 child 为原点,将 node 向左旋转
child.left = node
node.right = grandChild
// 更新节点高度
updateHeight(node)
updateHeight(child)
// 返回旋转后子树的根节点
return child
}
```
=== "Zig" === "Zig"
```zig title="avl_tree.zig" ```zig title="avl_tree.zig"
@@ -1504,6 +1574,40 @@ AVL 树的特点在于“旋转”操作,它能够在不影响二叉树的中
} }
``` ```
=== "Kotlin"
```kotlin title="avl_tree.kt"
/* 执行旋转操作,使该子树重新恢复平衡 */
fun rotate(node: TreeNode): TreeNode {
// 获取节点 node 的平衡因子
val balanceFactor = balanceFactor(node)
// 左偏树
if (balanceFactor > 1) {
if (balanceFactor(node.left) >= 0) {
// 右旋
return rightRotate(node)
} else {
// 先左旋后右旋
node.left = leftRotate(node.left)
return rightRotate(node)
}
}
// 右偏树
if (balanceFactor < -1) {
if (balanceFactor(node.right) <= 0) {
// 左旋
return leftRotate(node)
} else {
// 先右旋后左旋
node.right = rightRotate(node.right)
return leftRotate(node)
}
}
// 平衡树,无须旋转,直接返回
return node
}
```
=== "Zig" === "Zig"
```zig title="avl_tree.zig" ```zig title="avl_tree.zig"
@@ -1861,6 +1965,32 @@ AVL 树的节点插入操作与二叉搜索树在主体上类似。唯一的区
} }
``` ```
=== "Kotlin"
```kotlin title="avl_tree.kt"
/* 插入节点 */
fun insert(value: Int) {
root = insertHelper(root, value)
}
/* 递归插入节点(辅助方法) */
fun insertHelper(n: TreeNode?, value: Int): TreeNode {
if (n == null)
return TreeNode(value)
var node = n
/* 1. 查找插入位置并插入节点 */
if (value < node.value) node.left = insertHelper(node.left, value)
else if (value > node.value) node.right = insertHelper(node.right, value)
else return node // 重复节点不插入,直接返回
updateHeight(node) // 更新节点高度
/* 2. 执行旋转操作,使该子树重新恢复平衡 */
node = rotate(node)
// 返回子树的根节点
return node
}
```
=== "Zig" === "Zig"
```zig title="avl_tree.zig" ```zig title="avl_tree.zig"
@@ -2408,6 +2538,44 @@ AVL 树的节点插入操作与二叉搜索树在主体上类似。唯一的区
} }
``` ```
=== "Kotlin"
```kotlin title="avl_tree.kt"
/* 删除节点 */
fun remove(value: Int) {
root = removeHelper(root, value)
}
/* 递归删除节点(辅助方法) */
fun removeHelper(n: TreeNode?, value: Int): TreeNode? {
var node = n ?: return null
/* 1. 查找节点并删除 */
if (value < node.value) node.left = removeHelper(node.left, value)
else if (value > node.value) node.right = removeHelper(node.right, value)
else {
if (node.left == null || node.right == null) {
val child = if (node.left != null) node.left else node.right
// 子节点数量 = 0 ,直接删除 node 并返回
if (child == null) return null
else node = child
} else {
// 子节点数量 = 2 ,则将中序遍历的下个节点删除,并用该节点替换当前节点
var temp = node.right
while (temp!!.left != null) {
temp = temp.left
}
node.right = removeHelper(node.right, temp.value)
node.value = temp.value
}
}
updateHeight(node) // 更新节点高度
/* 2. 执行旋转操作,使该子树重新恢复平衡 */
node = rotate(node)
// 返回子树的根节点
return node
}
```
=== "Zig" === "Zig"
```zig title="avl_tree.zig" ```zig title="avl_tree.zig"
+97
View File
@@ -290,6 +290,26 @@ comments: true
} }
``` ```
=== "Kotlin"
```kotlin title="binary_search_tree.kt"
/* 查找节点 */
fun search(num: Int): TreeNode? {
var cur = root
// 循环查找,越过叶节点后跳出
while (cur != null) {
// 目标节点在 cur 的右子树中
cur = if (cur.value < num) cur.right
// 目标节点在 cur 的左子树中
else if (cur.value > num) cur.left
// 找到目标节点,跳出循环
else break
}
// 返回目标节点
return cur
}
```
=== "Zig" === "Zig"
```zig title="binary_search_tree.zig" ```zig title="binary_search_tree.zig"
@@ -707,6 +727,35 @@ comments: true
} }
``` ```
=== "Kotlin"
```kotlin title="binary_search_tree.kt"
/* 插入节点 */
fun insert(num: Int) {
// 若树为空,则初始化根节点
if (root == null) {
root = TreeNode(num)
return
}
var cur = root
var pre: TreeNode? = null
// 循环查找,越过叶节点后跳出
while (cur != null) {
// 找到重复节点,直接返回
if (cur.value == num) return
pre = cur
// 插入位置在 cur 的右子树中
cur = if (cur.value < num) cur.right
// 插入位置在 cur 的左子树中
else cur.left
}
// 插入节点
val node = TreeNode(num)
if (pre?.value!! < num) pre.right = node
else pre.left = node
}
```
=== "Zig" === "Zig"
```zig title="binary_search_tree.zig" ```zig title="binary_search_tree.zig"
@@ -1415,6 +1464,54 @@ comments: true
} }
``` ```
=== "Kotlin"
```kotlin title="binary_search_tree.kt"
/* 删除节点 */
fun remove(num: Int) {
// 若树为空,直接提前返回
if (root == null) return
var cur = root
var pre: TreeNode? = null
// 循环查找,越过叶节点后跳出
while (cur != null) {
// 找到待删除节点,跳出循环
if (cur.value == num) break
pre = cur
// 待删除节点在 cur 的右子树中
cur = if (cur.value < num) cur.right
// 待删除节点在 cur 的左子树中
else cur.left
}
// 若无待删除节点,则直接返回
if (cur == null) return
// 子节点数量 = 0 or 1
if (cur.left == null || cur.right == null) {
// 当子节点数量 = 0 / 1 时, child = null / 该子节点
val child = if (cur.left != null) cur.left else cur.right
// 删除节点 cur
if (cur != root) {
if (pre!!.left == cur) pre.left = child
else pre.right = child
} else {
// 若删除节点为根节点,则重新指定根节点
root = child
}
// 子节点数量 = 2
} else {
// 获取中序遍历中 cur 的下一个节点
var tmp = cur.right
while (tmp!!.left != null) {
tmp = tmp.left
}
// 递归删除节点 tmp
remove(tmp.value)
// 用 tmp 覆盖 cur
cur.value = tmp.value
}
}
```
=== "Zig" === "Zig"
```zig title="binary_search_tree.zig" ```zig title="binary_search_tree.zig"
+18
View File
@@ -180,6 +180,12 @@ comments: true
} }
``` ```
=== "Kotlin"
```kotlin title=""
```
=== "Zig" === "Zig"
```zig title="" ```zig title=""
@@ -405,6 +411,12 @@ comments: true
n2->right = n5; n2->right = n5;
``` ```
=== "Kotlin"
```kotlin title="binary_tree.kt"
```
=== "Zig" === "Zig"
```zig title="binary_tree.zig" ```zig title="binary_tree.zig"
@@ -553,6 +565,12 @@ comments: true
n1->left = n2; n1->left = n2;
``` ```
=== "Kotlin"
```kotlin title="binary_tree.kt"
```
=== "Zig" === "Zig"
```zig title="binary_tree.zig" ```zig title="binary_tree.zig"
@@ -293,6 +293,27 @@ comments: true
} }
``` ```
=== "Kotlin"
```kotlin title="binary_tree_bfs.kt"
/* 层序遍历 */
fun levelOrder(root: TreeNode?): MutableList<Int> {
// 初始化队列,加入根节点
val queue = LinkedList<TreeNode?>()
queue.add(root)
// 初始化一个列表,用于保存遍历序列
val list = ArrayList<Int>()
while (!queue.isEmpty()) {
val node = queue.poll() // 队列出队
list.add(node?.value!!) // 保存节点值
if (node.left != null) queue.offer(node.left) // 左子节点入队
if (node.right != null) queue.offer(node.right) // 右子节点入队
}
return list
}
```
=== "Zig" === "Zig"
```zig title="binary_tree_bfs.zig" ```zig title="binary_tree_bfs.zig"
@@ -729,6 +750,37 @@ comments: true
} }
``` ```
=== "Kotlin"
```kotlin title="binary_tree_dfs.kt"
/* 前序遍历 */
fun preOrder(root: TreeNode?) {
if (root == null) return
// 访问优先级:根节点 -> 左子树 -> 右子树
list.add(root.value)
preOrder(root.left)
preOrder(root.right)
}
/* 中序遍历 */
fun inOrder(root: TreeNode?) {
if (root == null) return
// 访问优先级:左子树 -> 根节点 -> 右子树
inOrder(root.left)
list.add(root.value)
inOrder(root.right)
}
/* 后序遍历 */
fun postOrder(root: TreeNode?) {
if (root == null) return
// 访问优先级:左子树 -> 右子树 -> 根节点
postOrder(root.left)
postOrder(root.right)
list.add(root.value)
}
```
=== "Zig" === "Zig"
```zig title="binary_tree_dfs.zig" ```zig title="binary_tree_dfs.zig"
@@ -111,6 +111,12 @@ Arrays can be initialized in two ways depending on the needs: either without ini
int nums[5] = { 1, 3, 2, 5, 4 }; int nums[5] = { 1, 3, 2, 5, 4 };
``` ```
=== "Kotlin"
```kotlin title="array.kt"
```
=== "Zig" === "Zig"
```zig title="array.zig" ```zig title="array.zig"
@@ -274,6 +280,19 @@ Accessing elements in an array is highly efficient, allowing us to randomly acce
} }
``` ```
=== "Kotlin"
```kotlin title="array.kt"
/* 随机访问元素 */
fun randomAccess(nums: IntArray): Int {
// 在区间 [0, nums.size) 中随机抽取一个数字
val randomIndex = ThreadLocalRandom.current().nextInt(0, nums.size)
// 获取并返回随机元素
val randomNum = nums[randomIndex]
return randomNum
}
```
=== "Zig" === "Zig"
```zig title="array.zig" ```zig title="array.zig"
@@ -454,6 +473,20 @@ It's important to note that due to the fixed length of an array, inserting an el
} }
``` ```
=== "Kotlin"
```kotlin title="array.kt"
/* 在数组的索引 index 处插入元素 num */
fun insert(nums: IntArray, num: Int, index: Int) {
// 把索引 index 以及之后的所有元素向后移动一位
for (i in nums.size - 1 downTo index + 1) {
nums[i] = nums[i - 1]
}
// 将 num 赋给 index 处的元素
nums[index] = num
}
```
=== "Zig" === "Zig"
```zig title="array.zig" ```zig title="array.zig"
@@ -615,6 +648,18 @@ Please note that after deletion, the former last element becomes "meaningless,"
} }
``` ```
=== "Kotlin"
```kotlin title="array.kt"
/* 删除索引 index 处的元素 */
fun remove(nums: IntArray, index: Int) {
// 把索引 index 之后的所有元素向前移动一位
for (i in index..<nums.size - 1) {
nums[i] = nums[i + 1]
}
}
```
=== "Zig" === "Zig"
```zig title="array.zig" ```zig title="array.zig"
@@ -838,6 +883,23 @@ In most programming languages, we can traverse an array either by using indices
} }
``` ```
=== "Kotlin"
```kotlin title="array.kt"
/* 遍历数组 */
fun traverse(nums: IntArray) {
var count = 0
// 通过索引遍历数组
for (i in nums.indices) {
count += nums[i]
}
// 直接遍历数组元素
for (j: Int in nums) {
count += j
}
}
```
=== "Zig" === "Zig"
```zig title="array.zig" ```zig title="array.zig"
@@ -1013,6 +1075,18 @@ Because arrays are linear data structures, this operation is commonly referred t
} }
``` ```
=== "Kotlin"
```kotlin title="array.kt"
/* 在数组中查找指定元素 */
fun find(nums: IntArray, target: Int): Int {
for (i in nums.indices) {
if (nums[i] == target) return i
}
return -1
}
```
=== "Zig" === "Zig"
```zig title="array.zig" ```zig title="array.zig"
@@ -1220,6 +1294,22 @@ To expand an array, it's necessary to create a larger array and then copy the e
} }
``` ```
=== "Kotlin"
```kotlin title="array.kt"
/* 扩展数组长度 */
fun extend(nums: IntArray, enlarge: Int): IntArray {
// 初始化一个扩展长度后的数组
val res = IntArray(nums.size + enlarge)
// 将原数组中的所有元素复制到新数组
for (i in nums.indices) {
res[i] = nums[i]
}
// 返回扩展后的新数组
return res
}
```
=== "Zig" === "Zig"
```zig title="array.zig" ```zig title="array.zig"
@@ -165,6 +165,12 @@ As the code below illustrates, a `ListNode` in a linked list, besides holding a
} }
``` ```
=== "Kotlin"
```kotlin title=""
```
=== "Zig" === "Zig"
```zig title="" ```zig title=""
@@ -379,6 +385,12 @@ Constructing a linked list is a two-step process: first, initializing each node
n3->next = n4; n3->next = n4;
``` ```
=== "Kotlin"
```kotlin title="linked_list.kt"
```
=== "Zig" === "Zig"
```zig title="linked_list.zig" ```zig title="linked_list.zig"
@@ -529,6 +541,17 @@ By comparison, inserting an element into an array has a time complexity of $O(n)
} }
``` ```
=== "Kotlin"
```kotlin title="linked_list.kt"
/* 在链表的节点 n0 之后插入节点p */
fun insert(n0: ListNode?, p: ListNode?) {
val n1 = n0?.next
p?.next = n1
n0?.next = p
}
```
=== "Zig" === "Zig"
```zig title="linked_list.zig" ```zig title="linked_list.zig"
@@ -718,6 +741,17 @@ It's important to note that even though node `P` continues to point to `n1` afte
} }
``` ```
=== "Kotlin"
```kotlin title="linked_list.kt"
/* 删除链表的节点 n0 之后的首个节点 */
fun remove(n0: ListNode?) {
val p = n0?.next
val n1 = p?.next
n0?.next = n1
}
```
=== "Zig" === "Zig"
```zig title="linked_list.zig" ```zig title="linked_list.zig"
@@ -898,6 +932,19 @@ It's important to note that even though node `P` continues to point to `n1` afte
} }
``` ```
=== "Kotlin"
```kotlin title="linked_list.kt"
/* 访问链表中索引为 index 的节点 */
fun access(head: ListNode?, index: Int): ListNode? {
var h = head
for (i in 0..<index) {
h = h?.next
}
return h
}
```
=== "Zig" === "Zig"
```zig title="linked_list.zig" ```zig title="linked_list.zig"
@@ -1101,6 +1148,22 @@ Traverse the linked list to locate a node whose value matches `target`, and then
} }
``` ```
=== "Kotlin"
```kotlin title="linked_list.kt"
/* 在链表中查找值为 target 的首个节点 */
fun find(head: ListNode?, target: Int): Int {
var index = 0
var h = head
while (h != null) {
if (h.value == target) return index
h = h.next
index++
}
return -1
}
```
=== "Zig" === "Zig"
```zig title="linked_list.zig" ```zig title="linked_list.zig"
@@ -1318,6 +1381,12 @@ As shown in the figure, there are three common types of linked lists.
} }
``` ```
=== "Kotlin"
```kotlin title=""
```
=== "Zig" === "Zig"
```zig title="" ```zig title=""
@@ -130,6 +130,12 @@ We typically use two initialization methods: "without initial values" and "with
// C does not provide built-in dynamic arrays // C does not provide built-in dynamic arrays
``` ```
=== "Kotlin"
```kotlin title="list.kt"
```
=== "Zig" === "Zig"
```zig title="list.zig" ```zig title="list.zig"
@@ -248,6 +254,12 @@ Lists are essentially arrays, thus they can access and update elements in $O(1)$
// C does not provide built-in dynamic arrays // C does not provide built-in dynamic arrays
``` ```
=== "Kotlin"
```kotlin title="list.kt"
```
=== "Zig" === "Zig"
```zig title="list.zig" ```zig title="list.zig"
@@ -468,6 +480,12 @@ Compared to arrays, lists offer more flexibility in adding and removing elements
// C does not provide built-in dynamic arrays // C does not provide built-in dynamic arrays
``` ```
=== "Kotlin"
```kotlin title="list.kt"
```
=== "Zig" === "Zig"
```zig title="list.zig" ```zig title="list.zig"
@@ -654,6 +672,12 @@ Similar to arrays, lists can be iterated either by using indices or by directly
// C does not provide built-in dynamic arrays // C does not provide built-in dynamic arrays
``` ```
=== "Kotlin"
```kotlin title="list.kt"
```
=== "Zig" === "Zig"
```zig title="list.zig" ```zig title="list.zig"
@@ -762,6 +786,12 @@ Given a new list `nums1`, we can append it to the end of the original list.
// C does not provide built-in dynamic arrays // C does not provide built-in dynamic arrays
``` ```
=== "Kotlin"
```kotlin title="list.kt"
```
=== "Zig" === "Zig"
```zig title="list.zig" ```zig title="list.zig"
@@ -852,6 +882,12 @@ Once the list is sorted, we can employ algorithms commonly used in array-related
// C does not provide built-in dynamic arrays // C does not provide built-in dynamic arrays
``` ```
=== "Kotlin"
```kotlin title="list.kt"
```
=== "Zig" === "Zig"
```zig title="list.zig" ```zig title="list.zig"
@@ -2005,6 +2041,106 @@ To enhance our understanding of how lists work, we will attempt to implement a s
} }
``` ```
=== "Kotlin"
```kotlin title="my_list.kt"
/* 列表类 */
class MyList {
private var arr: IntArray = intArrayOf() // 数组(存储列表元素)
private var capacity = 10 // 列表容量
private var size = 0 // 列表长度(当前元素数量)
private var extendRatio = 2 // 每次列表扩容的倍数
/* 构造函数 */
init {
arr = IntArray(capacity)
}
/* 获取列表长度(当前元素数量) */
fun size(): Int {
return size
}
/* 获取列表容量 */
fun capacity(): Int {
return capacity
}
/* 访问元素 */
fun get(index: Int): Int {
// 索引如果越界,则抛出异常,下同
if (index < 0 || index >= size)
throw IndexOutOfBoundsException()
return arr[index]
}
/* 更新元素 */
fun set(index: Int, num: Int) {
if (index < 0 || index >= size)
throw IndexOutOfBoundsException("索引越界")
arr[index] = num
}
/* 在尾部添加元素 */
fun add(num: Int) {
// 元素数量超出容量时,触发扩容机制
if (size == capacity())
extendCapacity()
arr[size] = num
// 更新元素数量
size++
}
/* 在中间插入元素 */
fun insert(index: Int, num: Int) {
if (index < 0 || index >= size)
throw IndexOutOfBoundsException("索引越界")
// 元素数量超出容量时,触发扩容机制
if (size == capacity())
extendCapacity()
// 将索引 index 以及之后的元素都向后移动一位
for (j in size - 1 downTo index)
arr[j + 1] = arr[j]
arr[index] = num
// 更新元素数量
size++
}
/* 删除元素 */
fun remove(index: Int): Int {
if (index < 0 || index >= size)
throw IndexOutOfBoundsException("索引越界")
val num: Int = arr[index]
// 将将索引 index 之后的元素都向前移动一位
for (j in index..<size - 1)
arr[j] = arr[j + 1]
// 更新元素数量
size--
// 返回被删除的元素
return num
}
/* 列表扩容 */
fun extendCapacity() {
// 新建一个长度为原数组 extendRatio 倍的新数组,并将原数组复制到新数组
arr = arr.copyOf(capacity() * extendRatio)
// 更新列表容量
capacity = arr.size
}
/* 将列表转换为数组 */
fun toArray(): IntArray {
val size = size()
// 仅转换有效长度范围内的列表元素
val arr = IntArray(size)
for (i in 0..<size) {
arr[i] = get(i)
}
return arr
}
}
```
=== "Zig" === "Zig"
```zig title="my_list.zig" ```zig title="my_list.zig"
@@ -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"
```zig title="iteration.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"
```zig title="iteration.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"
```zig title="iteration.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"
```zig title="iteration.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"
```zig title="recursion.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"
```zig title="recursion.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"
```zig title="recursion.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"
```zig title="recursion.zig" ```zig title="recursion.zig"
@@ -316,6 +316,12 @@ The relevant code is as follows:
} }
``` ```
=== "Kotlin"
```kotlin title=""
```
=== "Zig" === "Zig"
```zig title="" ```zig title=""
@@ -462,6 +468,12 @@ Consider the following code, the term "worst-case" in worst-case space complexit
} }
``` ```
=== "Kotlin"
```kotlin title=""
```
=== "Zig" === "Zig"
```zig title="" ```zig title=""
@@ -482,9 +494,10 @@ Consider the following code, the term "worst-case" in worst-case space complexit
for _ in range(n): for _ in range(n):
function() function()
def recur(n: int) -> int: def recur(n: int):
"""Recursion O(n)""""" """Recursion O(n)"""""
if n == 1: return if n == 1:
return
return recur(n - 1) 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"
```zig title="" ```zig title=""
@@ -725,7 +744,7 @@ $$
<p align="center"> Figure 2-16 &nbsp; Common Types of Space Complexity </p> <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$. 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"
```zig title="space_complexity.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="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> <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$: 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"
```zig title="space_complexity.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"
```zig title="space_complexity.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> <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$: 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"
```zig title="space_complexity.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"
```zig title="space_complexity.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> <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: 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"
```zig title="space_complexity.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> <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. 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"
```zig title="" ```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"
```zig title="" ```zig title=""
@@ -629,6 +641,12 @@ Consider a function with an input size of $n$:
} }
``` ```
=== "Kotlin"
```kotlin title=""
```
=== "Zig" === "Zig"
```zig title="" ```zig title=""
@@ -886,6 +904,12 @@ Given a function, we can use these techniques to count operations:
} }
``` ```
=== "Kotlin"
```kotlin title=""
```
=== "Zig" === "Zig"
```zig title="" ```zig title=""
@@ -952,7 +976,7 @@ $$
<p align="center"> Figure 2-9 &nbsp; Common Types of Time Complexity </p> <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$: 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"
```zig title="time_complexity.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="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> <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: 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"
```zig title="time_complexity.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"
```zig title="time_complexity.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. 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)$: 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"
```zig title="time_complexity.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"
```zig title="time_complexity.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="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> <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. 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"
```zig title="time_complexity.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"
```zig title="time_complexity.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. 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$. 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"
```zig title="time_complexity.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"
```zig title="time_complexity.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)$. 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: 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"
```zig title="time_complexity.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. 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: 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"
```zig title="time_complexity.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"
```zig title="worst_best_time_complexity.zig" ```zig title="worst_best_time_complexity.zig"
@@ -161,6 +161,12 @@ In other words, **basic data types provide the "content type" of data, while dat
bool bools[10]; bool bools[10];
``` ```
=== "Kotlin"
```kotlin title=""
```
=== "Zig" === "Zig"
```zig title="" ```zig title=""
+46
View File
@@ -554,6 +554,46 @@ The design of hash algorithms is a complex issue that requires consideration of
} }
``` ```
=== "Kotlin"
```kotlin title="simple_hash.kt"
/* 加法哈希 */
fun addHash(key: String): Int {
var hash = 0L
for (c in key.toCharArray()) {
hash = (hash + c.code) % MODULUS
}
return hash.toInt()
}
/* 乘法哈希 */
fun mulHash(key: String): Int {
var hash = 0L
for (c in key.toCharArray()) {
hash = (31 * hash + c.code) % MODULUS
}
return hash.toInt()
}
/* 异或哈希 */
fun xorHash(key: String): Int {
var hash = 0
for (c in key.toCharArray()) {
hash = hash xor c.code
}
return hash and MODULUS
}
/* 旋转哈希 */
fun rotHash(key: String): Int {
var hash = 0L
for (c in key.toCharArray()) {
hash = ((hash shl 4) xor (hash shr 28) xor c.code.toLong()) % MODULUS
}
return hash.toInt()
}
```
=== "Zig" === "Zig"
```zig title="simple_hash.zig" ```zig title="simple_hash.zig"
@@ -868,6 +908,12 @@ We know that the keys in a hash table can be of various data types such as integ
// C does not provide built-in hash code functions // C does not provide built-in hash code functions
``` ```
=== "Kotlin"
```kotlin title="built_in_hash.kt"
```
=== "Zig" === "Zig"
```zig title="built_in_hash.zig" ```zig title="built_in_hash.zig"
+241
View File
@@ -1311,6 +1311,121 @@ The code below provides a simple implementation of a separate chaining hash tabl
} }
``` ```
=== "Kotlin"
```kotlin title="hash_map_chaining.kt"
/* 链式地址哈希表 */
class HashMapChaining() {
var size: Int // 键值对数量
var capacity: Int // 哈希表容量
val loadThres: Double // 触发扩容的负载因子阈值
val extendRatio: Int // 扩容倍数
var buckets: MutableList<MutableList<Pair>> // 桶数组
/* 构造方法 */
init {
size = 0
capacity = 4
loadThres = 2.0 / 3.0
extendRatio = 2
buckets = ArrayList(capacity)
for (i in 0..<capacity) {
buckets.add(mutableListOf())
}
}
/* 哈希函数 */
fun hashFunc(key: Int): Int {
return key % capacity
}
/* 负载因子 */
fun loadFactor(): Double {
return (size / capacity).toDouble()
}
/* 查询操作 */
fun get(key: Int): String? {
val index = hashFunc(key)
val bucket = buckets[index]
// 遍历桶,若找到 key ,则返回对应 val
for (pair in bucket) {
if (pair.key == key) return pair.value
}
// 若未找到 key ,则返回 null
return null
}
/* 添加操作 */
fun put(key: Int, value: String) {
// 当负载因子超过阈值时,执行扩容
if (loadFactor() > loadThres) {
extend()
}
val index = hashFunc(key)
val bucket = buckets[index]
// 遍历桶,若遇到指定 key ,则更新对应 val 并返回
for (pair in bucket) {
if (pair.key == key) {
pair.value = value
return
}
}
// 若无该 key ,则将键值对添加至尾部
val pair = Pair(key, value)
bucket.add(pair)
size++
}
/* 删除操作 */
fun remove(key: Int) {
val index = hashFunc(key)
val bucket = buckets[index]
// 遍历桶,从中删除键值对
for (pair in bucket) {
if (pair.key == key) {
bucket.remove(pair)
size--
break
}
}
}
/* 扩容哈希表 */
fun extend() {
// 暂存原哈希表
val bucketsTmp = buckets
// 初始化扩容后的新哈希表
capacity *= extendRatio
// mutablelist 无固定大小
buckets = mutableListOf()
for (i in 0..<capacity) {
buckets.add(mutableListOf())
}
size = 0
// 将键值对从原哈希表搬运至新哈希表
for (bucket in bucketsTmp) {
for (pair in bucket) {
put(pair.key, pair.value)
}
}
}
/* 打印哈希表 */
fun print() {
for (bucket in buckets) {
val res = mutableListOf<String>()
for (pair in bucket) {
val k = pair.key
val v = pair.value
res.add("$k -> $v")
}
println(res)
}
}
}
```
=== "Zig" === "Zig"
```zig title="hash_map_chaining.zig" ```zig title="hash_map_chaining.zig"
@@ -2831,6 +2946,132 @@ The code below implements an open addressing (linear probing) hash table with la
} }
``` ```
=== "Kotlin"
```kotlin title="hash_map_open_addressing.kt"
/* 开放寻址哈希表 */
class HashMapOpenAddressing {
private var size: Int = 0 // 键值对数量
private var capacity = 4 // 哈希表容量
private val loadThres: Double = 2.0 / 3.0 // 触发扩容的负载因子阈值
private val extendRatio = 2 // 扩容倍数
private var buckets: Array<Pair?> // 桶数组
private val TOMBSTONE = Pair(-1, "-1") // 删除标记
/* 构造方法 */
init {
buckets = arrayOfNulls(capacity)
}
/* 哈希函数 */
fun hashFunc(key: Int): Int {
return key % capacity
}
/* 负载因子 */
fun loadFactor(): Double {
return (size / capacity).toDouble()
}
/* 搜索 key 对应的桶索引 */
fun findBucket(key: Int): Int {
var index = hashFunc(key)
var firstTombstone = -1
// 线性探测,当遇到空桶时跳出
while (buckets[index] != null) {
// 若遇到 key ,返回对应的桶索引
if (buckets[index]?.key == key) {
// 若之前遇到了删除标记,则将键值对移动至该索引处
if (firstTombstone != -1) {
buckets[firstTombstone] = buckets[index]
buckets[index] = TOMBSTONE
return firstTombstone // 返回移动后的桶索引
}
return index // 返回桶索引
}
// 记录遇到的首个删除标记
if (firstTombstone == -1 && buckets[index] == TOMBSTONE) {
firstTombstone = index
}
// 计算桶索引,越过尾部则返回头部
index = (index + 1) % capacity
}
// 若 key 不存在,则返回添加点的索引
return if (firstTombstone == -1) index else firstTombstone
}
/* 查询操作 */
fun get(key: Int): String? {
// 搜索 key 对应的桶索引
val index = findBucket(key)
// 若找到键值对,则返回对应 val
if (buckets[index] != null && buckets[index] != TOMBSTONE) {
return buckets[index]?.value
}
// 若键值对不存在,则返回 null
return null
}
/* 添加操作 */
fun put(key: Int, value: String) {
// 当负载因子超过阈值时,执行扩容
if (loadFactor() > loadThres) {
extend()
}
// 搜索 key 对应的桶索引
val index = findBucket(key)
// 若找到键值对,则覆盖 val 并返回
if (buckets[index] != null && buckets[index] != TOMBSTONE) {
buckets[index]!!.value = value
return
}
// 若键值对不存在,则添加该键值对
buckets[index] = Pair(key, value)
size++
}
/* 删除操作 */
fun remove(key: Int) {
// 搜索 key 对应的桶索引
val index = findBucket(key)
// 若找到键值对,则用删除标记覆盖它
if (buckets[index] != null && buckets[index] != TOMBSTONE) {
buckets[index] = TOMBSTONE
size--
}
}
/* 扩容哈希表 */
fun extend() {
// 暂存原哈希表
val bucketsTmp = buckets
// 初始化扩容后的新哈希表
capacity *= extendRatio
buckets = arrayOfNulls(capacity)
size = 0
// 将键值对从原哈希表搬运至新哈希表
for (pair in bucketsTmp) {
if (pair != null && pair != TOMBSTONE) {
put(pair.key, pair.value)
}
}
}
/* 打印哈希表 */
fun print() {
for (pair in buckets) {
if (pair == null) {
println("null")
} else if (pair == TOMBSTONE) {
println("TOMESTOME")
} else {
println("${pair.key} -> ${pair.value}")
}
}
}
}
```
=== "Zig" === "Zig"
```zig title="hash_map_open_addressing.zig" ```zig title="hash_map_open_addressing.zig"
+172
View File
@@ -277,6 +277,12 @@ Common operations of a hash table include initialization, querying, adding key-v
// C does not provide a built-in hash table // C does not provide a built-in hash table
``` ```
=== "Kotlin"
```kotlin title="hash_map.kt"
```
=== "Zig" === "Zig"
```zig title="hash_map.zig" ```zig title="hash_map.zig"
@@ -473,6 +479,12 @@ There are three common ways to traverse a hash table: traversing key-value pairs
// C does not provide a built-in hash table // C does not provide a built-in hash table
``` ```
=== "Kotlin"
```kotlin title="hash_map.kt"
```
=== "Zig" === "Zig"
```zig title="hash_map.zig" ```zig title="hash_map.zig"
@@ -1525,6 +1537,166 @@ The following code implements a simple hash table. Here, we encapsulate `key` an
} }
``` ```
=== "Kotlin"
```kotlin title="array_hash_map.kt"
/* 键值对 */
class Pair(
var key: Int,
var value: String
)
/* 基于数组实现的哈希表 */
class ArrayHashMap {
private val buckets = arrayOfNulls<Pair>(100)
init {
// 初始化数组,包含 100 个桶
for (i in 0..<100) {
buckets[i] = null
}
}
/* 哈希函数 */
fun hashFunc(key: Int): Int {
val index = key % 100
return index
}
/* 查询操作 */
fun get(key: Int): String? {
val index = hashFunc(key)
val pair = buckets[index] ?: return null
return pair.value
}
/* 添加操作 */
fun put(key: Int, value: String) {
val pair = Pair(key, value)
val index = hashFunc(key)
buckets[index] = pair
}
/* 删除操作 */
fun remove(key: Int) {
val index = hashFunc(key)
// 置为 null ,代表删除
buckets[index] = null
}
/* 获取所有键值对 */
fun pairSet(): MutableList<Pair> {
val pairSet = ArrayList<Pair>()
for (pair in buckets) {
if (pair != null) pairSet.add(pair)
}
return pairSet
}
/* 获取所有键 */
fun keySet(): MutableList<Int> {
val keySet = ArrayList<Int>()
for (pair in buckets) {
if (pair != null) keySet.add(pair.key)
}
return keySet
}
/* 获取所有值 */
fun valueSet(): MutableList<String> {
val valueSet = ArrayList<String>()
for (pair in buckets) {
pair?.let { valueSet.add(it.value) }
}
return valueSet
}
/* 打印哈希表 */
fun print() {
for (kv in pairSet()) {
val key = kv.key
val value = kv.value
println("${key}->${value}")
}
}
}
/* 基于数组实现的哈希表 */
class ArrayHashMap {
private val buckets = arrayOfNulls<Pair>(100)
init {
// 初始化数组,包含 100 个桶
for (i in 0..<100) {
buckets[i] = null
}
}
/* 哈希函数 */
fun hashFunc(key: Int): Int {
val index = key % 100
return index
}
/* 查询操作 */
fun get(key: Int): String? {
val index = hashFunc(key)
val pair = buckets[index] ?: return null
return pair.value
}
/* 添加操作 */
fun put(key: Int, value: String) {
val pair = Pair(key, value)
val index = hashFunc(key)
buckets[index] = pair
}
/* 删除操作 */
fun remove(key: Int) {
val index = hashFunc(key)
// 置为 null ,代表删除
buckets[index] = null
}
/* 获取所有键值对 */
fun pairSet(): MutableList<Pair> {
val pairSet = ArrayList<Pair>()
for (pair in buckets) {
if (pair != null) pairSet.add(pair)
}
return pairSet
}
/* 获取所有键 */
fun keySet(): MutableList<Int> {
val keySet = ArrayList<Int>()
for (pair in buckets) {
if (pair != null) keySet.add(pair.key)
}
return keySet
}
/* 获取所有值 */
fun valueSet(): MutableList<String> {
val valueSet = ArrayList<String>()
for (pair in buckets) {
pair?.let { valueSet.add(it.value) }
}
return valueSet
}
/* 打印哈希表 */
fun print() {
for (kv in pairSet()) {
val key = kv.key
val value = kv.value
println("${key}->${value}")
}
}
}
```
=== "Zig" === "Zig"
```zig title="array_hash_map.zig" ```zig title="array_hash_map.zig"
+13
View File
@@ -160,6 +160,19 @@ comments: true
*/ */
``` ```
=== "Kotlin"
```kotlin title=""
/* Header comments for labeling functions, classes, test samples, etc */
// Comments for explaining details.
/**
* Multiline
* comments
*/
```
=== "Zig" === "Zig"
```zig title="" ```zig title=""
File diff suppressed because it is too large Load Diff
+140
View File
@@ -312,6 +312,12 @@ We can directly use the ready-made queue classes in programming languages:
// C does not provide a built-in queue // C does not provide a built-in queue
``` ```
=== "Kotlin"
```kotlin title="queue.kt"
```
=== "Zig" === "Zig"
```zig title="queue.zig" ```zig title="queue.zig"
@@ -1125,6 +1131,71 @@ Below is the code for implementing a queue using a linked list:
} }
``` ```
=== "Kotlin"
```kotlin title="linkedlist_queue.kt"
/* 基于链表实现的队列 */
class LinkedListQueue(
// 头节点 front ,尾节点 rear
private var front: ListNode? = null,
private var rear: ListNode? = null,
private var queSize: Int = 0
) {
/* 获取队列的长度 */
fun size(): Int {
return queSize
}
/* 判断队列是否为空 */
fun isEmpty(): Boolean {
return size() == 0
}
/* 入队 */
fun push(num: Int) {
// 在尾节点后添加 num
val node = ListNode(num)
// 如果队列为空,则令头、尾节点都指向该节点
if (front == null) {
front = node
rear = node
// 如果队列不为空,则将该节点添加到尾节点后
} else {
rear?.next = node
rear = node
}
queSize++
}
/* 出队 */
fun pop(): Int {
val num = peek()
// 删除头节点
front = front?.next
queSize--
return num
}
/* 访问队首元素 */
fun peek(): Int {
if (isEmpty()) throw IndexOutOfBoundsException()
return front!!.value
}
/* 将链表转化为 Array 并返回 */
fun toArray(): IntArray {
var node = front
val res = IntArray(size())
for (i in res.indices) {
res[i] = node!!.value
node = node.next
}
return res
}
}
```
=== "Zig" === "Zig"
```zig title="linkedlist_queue.zig" ```zig title="linkedlist_queue.zig"
@@ -2036,6 +2107,75 @@ In a circular array, `front` or `rear` needs to loop back to the start of the ar
} }
``` ```
=== "Kotlin"
```kotlin title="array_queue.kt"
/* 基于环形数组实现的队列 */
class ArrayQueue(capacity: Int) {
private val nums = IntArray(capacity) // 用于存储队列元素的数组
private var front = 0 // 队首指针,指向队首元素
private var queSize = 0 // 队列长度
/* 获取队列的容量 */
fun capacity(): Int {
return nums.size
}
/* 获取队列的长度 */
fun size(): Int {
return queSize
}
/* 判断队列是否为空 */
fun isEmpty(): Boolean {
return queSize == 0
}
/* 入队 */
fun push(num: Int) {
if (queSize == capacity()) {
println("队列已满")
return
}
// 计算队尾指针,指向队尾索引 + 1
// 通过取余操作实现 rear 越过数组尾部后回到头部
val rear = (front + queSize) % capacity()
// 将 num 添加至队尾
nums[rear] = num
queSize++
}
/* 出队 */
fun pop(): Int {
val num = peek()
// 队首指针向后移动一位,若越过尾部,则返回到数组头部
front = (front + 1) % capacity()
queSize--
return num
}
/* 访问队首元素 */
fun peek(): Int {
if (isEmpty()) throw IndexOutOfBoundsException()
return nums[front]
}
/* 返回数组 */
fun toArray(): IntArray {
// 仅转换有效长度范围内的列表元素
val res = IntArray(queSize)
var i = 0
var j = front
while (i < queSize) {
res[i] = nums[j % capacity()]
i++
j++
}
return res
}
}
```
=== "Zig" === "Zig"
```zig title="array_queue.zig" ```zig title="array_queue.zig"
+102
View File
@@ -306,6 +306,12 @@ Typically, we can directly use the stack class built into the programming langua
// C does not provide a built-in stack // C does not provide a built-in stack
``` ```
=== "Kotlin"
```kotlin title="stack.kt"
```
=== "Zig" === "Zig"
```zig title="stack.zig" ```zig title="stack.zig"
@@ -1008,6 +1014,60 @@ Below is an example code for implementing a stack based on a linked list:
} }
``` ```
=== "Kotlin"
```kotlin title="linkedlist_stack.kt"
/* 基于链表实现的栈 */
class LinkedListStack(
private var stackPeek: ListNode? = null, // 将头节点作为栈顶
private var stkSize: Int = 0 // 栈的长度
) {
/* 获取栈的长度 */
fun size(): Int {
return stkSize
}
/* 判断栈是否为空 */
fun isEmpty(): Boolean {
return size() == 0
}
/* 入栈 */
fun push(num: Int) {
val node = ListNode(num)
node.next = stackPeek
stackPeek = node
stkSize++
}
/* 出栈 */
fun pop(): Int? {
val num = peek()
stackPeek = stackPeek?.next
stkSize--;
return num
}
/* 访问栈顶元素 */
fun peek(): Int? {
if (isEmpty()) throw IndexOutOfBoundsException()
return stackPeek?.value
}
/* 将 List 转化为 Array 并返回 */
fun toArray(): IntArray {
var node = stackPeek
val res = IntArray(size())
for (i in res.size - 1 downTo 0) {
res[i] = node?.value!!
node = node.next
}
return res
}
}
```
=== "Zig" === "Zig"
```zig title="linkedlist_stack.zig" ```zig title="linkedlist_stack.zig"
@@ -1643,6 +1703,48 @@ Since the elements to be pushed onto the stack may continuously increase, we can
} }
``` ```
=== "Kotlin"
```kotlin title="array_stack.kt"
/* 基于数组实现的栈 */
class ArrayStack {
// 初始化列表(动态数组)
private val stack = ArrayList<Int>()
/* 获取栈的长度 */
fun size(): Int {
return stack.size
}
/* 判断栈是否为空 */
fun isEmpty(): Boolean {
return size() == 0
}
/* 入栈 */
fun push(num: Int) {
stack.add(num)
}
/* 出栈 */
fun pop(): Int {
if (isEmpty()) throw IndexOutOfBoundsException()
return stack.removeAt(size() - 1)
}
/* 访问栈顶元素 */
fun peek(): Int {
if (isEmpty()) throw IndexOutOfBoundsException()
return stack[size() - 1]
}
/* 将 List 转化为 Array 并返回 */
fun toArray(): Array<Any> {
return stack.toArray()
}
}
```
=== "Zig" === "Zig"
```zig title="array_stack.zig" ```zig title="array_stack.zig"
+5
View File
@@ -207,6 +207,11 @@ body {
width: 1.25em; width: 1.25em;
} }
/* code block tabs */
.md-typeset .tabbed-labels>label {
font-size: 0.59rem;
}
/* header banner */ /* header banner */
.md-banner { .md-banner {
background-color: var(--md-code-bg-color); background-color: var(--md-code-bg-color);