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