From cfdb7439394f23fc4d1fda796bc524e1a0ecdac8 Mon Sep 17 00:00:00 2001 From: krahets Date: Thu, 21 Mar 2024 04:22:07 +0800 Subject: [PATCH] build --- docs-en/chapter_array_and_linkedlist/array.md | 5 +++ .../linked_list.md | 1 - docs-en/chapter_array_and_linkedlist/list.md | 35 +++++++-------- .../iteration_and_recursion.md | 2 +- .../time_complexity.md | 4 +- .../basic_data_types.md | 8 ++-- docs-en/chapter_hashing/hash_collision.md | 7 +-- docs-en/chapter_hashing/hash_map.md | 30 +++---------- docs-en/chapter_stack_and_queue/deque.md | 24 ++++++---- docs-en/chapter_stack_and_queue/queue.md | 28 ++++++------ docs-en/chapter_stack_and_queue/stack.md | 10 +++-- docs/chapter_appendix/terminology.md | 31 +++++++------ docs/chapter_array_and_linkedlist/array.md | 5 +++ .../linked_list.md | 1 - docs/chapter_array_and_linkedlist/list.md | 35 +++++++-------- .../subset_sum_problem.md | 6 +-- .../iteration_and_recursion.md | 2 +- .../time_complexity.md | 4 +- .../basic_data_types.md | 8 ++-- .../binary_search_recur.md | 3 +- .../build_binary_tree_problem.md | 2 +- .../dp_problem_features.md | 6 +-- .../dp_solution_pipeline.md | 14 +++--- .../edit_distance_problem.md | 14 +++--- .../intro_to_dynamic_programming.md | 4 +- .../knapsack_problem.md | 8 ++-- .../unbounded_knapsack_problem.md | 28 ++++++------ docs/chapter_graph/graph_operations.md | 15 +++---- .../fractional_knapsack_problem.md | 2 +- docs/chapter_greedy/max_capacity_problem.md | 2 +- docs/chapter_hashing/hash_collision.md | 7 +-- docs/chapter_hashing/hash_map.md | 30 +++---------- docs/chapter_heap/build_heap.md | 2 +- docs/chapter_heap/heap.md | 30 ++++++++++++- docs/chapter_heap/top_k.md | 2 +- docs/chapter_searching/binary_search.md | 8 ++-- docs/chapter_searching/binary_search_edge.md | 2 +- .../binary_search_insertion.md | 8 +++- docs/chapter_sorting/bubble_sort.md | 16 +++---- docs/chapter_sorting/bucket_sort.md | 2 +- docs/chapter_sorting/counting_sort.md | 10 ++--- docs/chapter_sorting/heap_sort.md | 2 +- docs/chapter_sorting/insertion_sort.md | 2 +- docs/chapter_sorting/merge_sort.md | 3 +- docs/chapter_sorting/quick_sort.md | 19 +++----- docs/chapter_sorting/radix_sort.md | 5 +-- docs/chapter_stack_and_queue/deque.md | 44 ++++++++++--------- docs/chapter_stack_and_queue/queue.md | 28 ++++++------ docs/chapter_stack_and_queue/stack.md | 10 +++-- .../array_representation_of_tree.md | 2 +- docs/chapter_tree/avl_tree.md | 4 +- docs/chapter_tree/binary_search_tree.md | 2 +- 52 files changed, 292 insertions(+), 290 deletions(-) diff --git a/docs-en/chapter_array_and_linkedlist/array.md b/docs-en/chapter_array_and_linkedlist/array.md index 499562d0b..b8cc64c99 100755 --- a/docs-en/chapter_array_and_linkedlist/array.md +++ b/docs-en/chapter_array_and_linkedlist/array.md @@ -745,6 +745,11 @@ In most programming languages, we can traverse an array either by using indices for num in nums { count += num } + // 同时遍历数据索引和元素 + for (i, num) in nums.enumerated() { + count += nums[i] + count += num + } } ``` diff --git a/docs-en/chapter_array_and_linkedlist/linked_list.md b/docs-en/chapter_array_and_linkedlist/linked_list.md index bfd32b4dd..e9adc4148 100755 --- a/docs-en/chapter_array_and_linkedlist/linked_list.md +++ b/docs-en/chapter_array_and_linkedlist/linked_list.md @@ -639,7 +639,6 @@ It's important to note that even though node `P` continues to point to `n1` afte let P = n0.next let n1 = P?.next n0.next = n1 - P?.next = nil } ``` diff --git a/docs-en/chapter_array_and_linkedlist/list.md b/docs-en/chapter_array_and_linkedlist/list.md index f2daca28b..da74cd799 100755 --- a/docs-en/chapter_array_and_linkedlist/list.md +++ b/docs-en/chapter_array_and_linkedlist/list.md @@ -1382,12 +1382,15 @@ To enhance our understanding of how lists work, we will attempt to implement a s /* 列表类 */ class MyList { private var arr: [Int] // 数组(存储列表元素) - private var _capacity = 10 // 列表容量 - private var _size = 0 // 列表长度(当前元素数量) - private let extendRatio = 2 // 每次列表扩容的倍数 + private var _capacity: Int // 列表容量 + private var _size: Int // 列表长度(当前元素数量) + private let extendRatio: Int // 每次列表扩容的倍数 /* 构造方法 */ init() { + _capacity = 10 + _size = 0 + extendRatio = 2 arr = Array(repeating: 0, count: _capacity) } @@ -1404,7 +1407,7 @@ To enhance our understanding of how lists work, we will attempt to implement a s /* 访问元素 */ func get(index: Int) -> Int { // 索引如果越界则抛出错误,下同 - if index < 0 || index >= _size { + if index < 0 || index >= size() { fatalError("索引越界") } return arr[index] @@ -1412,7 +1415,7 @@ To enhance our understanding of how lists work, we will attempt to implement a s /* 更新元素 */ func set(index: Int, num: Int) { - if index < 0 || index >= _size { + if index < 0 || index >= size() { fatalError("索引越界") } arr[index] = num @@ -1421,25 +1424,25 @@ To enhance our understanding of how lists work, we will attempt to implement a s /* 在尾部添加元素 */ func add(num: Int) { // 元素数量超出容量时,触发扩容机制 - if _size == _capacity { + if size() == capacity() { extendCapacity() } - arr[_size] = num + arr[size()] = num // 更新元素数量 _size += 1 } /* 在中间插入元素 */ func insert(index: Int, num: Int) { - if index < 0 || index >= _size { + if index < 0 || index >= size() { fatalError("索引越界") } // 元素数量超出容量时,触发扩容机制 - if _size == _capacity { + if size() == capacity() { extendCapacity() } // 将索引 index 以及之后的元素都向后移动一位 - for j in sequence(first: _size - 1, next: { $0 >= index + 1 ? $0 - 1 : nil }) { + for j in (index ..< size()).reversed() { arr[j + 1] = arr[j] } arr[index] = num @@ -1450,12 +1453,12 @@ To enhance our understanding of how lists work, we will attempt to implement a s /* 删除元素 */ @discardableResult func remove(index: Int) -> Int { - if index < 0 || index >= _size { + if index < 0 || index >= size() { fatalError("索引越界") } let num = arr[index] // 将将索引 index 之后的元素都向前移动一位 - for j in index ..< (_size - 1) { + for j in index ..< (size() - 1) { arr[j] = arr[j + 1] } // 更新元素数量 @@ -1467,18 +1470,14 @@ To enhance our understanding of how lists work, we will attempt to implement a s /* 列表扩容 */ func extendCapacity() { // 新建一个长度为原数组 extendRatio 倍的新数组,并将原数组复制到新数组 - arr = arr + Array(repeating: 0, count: _capacity * (extendRatio - 1)) + arr = arr + Array(repeating: 0, count: capacity() * (extendRatio - 1)) // 更新列表容量 _capacity = arr.count } /* 将列表转换为数组 */ func toArray() -> [Int] { - var arr = Array(repeating: 0, count: _size) - for i in 0 ..< _size { - arr[i] = get(index: i) - } - return arr + Array(arr.prefix(size())) } } ``` diff --git a/docs-en/chapter_computational_complexity/iteration_and_recursion.md b/docs-en/chapter_computational_complexity/iteration_and_recursion.md index 88da24a19..0294c9c32 100644 --- a/docs-en/chapter_computational_complexity/iteration_and_recursion.md +++ b/docs-en/chapter_computational_complexity/iteration_and_recursion.md @@ -1631,7 +1631,7 @@ Therefore, **we can use an explicit stack to simulate the behavior of the call s var stack: [Int] = [] var res = 0 // 递:递归调用 - for i in stride(from: n, to: 0, by: -1) { + for i in (1 ... n).reversed() { // 通过“入栈操作”模拟“递” stack.append(i) } diff --git a/docs-en/chapter_computational_complexity/time_complexity.md b/docs-en/chapter_computational_complexity/time_complexity.md index 4dc7c0ae8..f281fa99e 100644 --- a/docs-en/chapter_computational_complexity/time_complexity.md +++ b/docs-en/chapter_computational_complexity/time_complexity.md @@ -321,7 +321,7 @@ Let's understand this concept of "time growth trend" with an example. Assume the // Time complexity of algorithm C: constant order func algorithmC(n: Int) { - for _ in 0 ..< 1000000 { + for _ in 0 ..< 1_000_000 { print(0) } } @@ -1780,7 +1780,7 @@ For instance, in bubble sort, the outer loop runs $n - 1$ times, and the inner l func bubbleSort(nums: inout [Int]) -> Int { var count = 0 // 计数器 // 外循环:未排序区间为 [0, i] - for i in stride(from: nums.count - 1, to: 0, by: -1) { + for i in nums.indices.dropFirst().reversed() { // 内循环:将未排序区间 [0, i] 中的最大元素交换至该区间的最右端 for j in 0 ..< i { if nums[j] > nums[j + 1] { diff --git a/docs-en/chapter_data_structure/basic_data_types.md b/docs-en/chapter_data_structure/basic_data_types.md index 69803de80..f1707fa91 100644 --- a/docs-en/chapter_data_structure/basic_data_types.md +++ b/docs-en/chapter_data_structure/basic_data_types.md @@ -109,10 +109,10 @@ In other words, **basic data types provide the "content type" of data, while dat ```swift title="" // Using various basic data types to initialize arrays - let numbers = Array(repeating: Int(), count: 5) - let decimals = Array(repeating: Double(), count: 5) - let characters = Array(repeating: Character("a"), count: 5) - let bools = Array(repeating: Bool(), count: 5) + let numbers = Array(repeating: 0, count: 5) + let decimals = Array(repeating: 0.0, count: 5) + let characters: [Character] = Array(repeating: "a", count: 5) + let bools = Array(repeating: false, count: 5) ``` === "JS" diff --git a/docs-en/chapter_hashing/hash_collision.md b/docs-en/chapter_hashing/hash_collision.md index 755d4a80e..e44574e6f 100644 --- a/docs-en/chapter_hashing/hash_collision.md +++ b/docs-en/chapter_hashing/hash_collision.md @@ -618,7 +618,7 @@ The code below provides a simple implementation of a separate chaining hash tabl /* 负载因子 */ func loadFactor() -> Double { - Double(size / capacity) + Double(size) / Double(capacity) } /* 查询操作 */ @@ -664,9 +664,10 @@ The code below provides a simple implementation of a separate chaining hash tabl for (pairIndex, pair) in bucket.enumerated() { if pair.key == key { buckets[index].remove(at: pairIndex) + size -= 1 + break } } - size -= 1 } /* 扩容哈希表 */ @@ -2004,7 +2005,7 @@ The code below implements an open addressing (linear probing) hash table with la /* 负载因子 */ func loadFactor() -> Double { - Double(size / capacity) + Double(size) / Double(capacity) } /* 搜索 key 对应的桶索引 */ diff --git a/docs-en/chapter_hashing/hash_map.md b/docs-en/chapter_hashing/hash_map.md index 6236774fc..e05ff9b2a 100755 --- a/docs-en/chapter_hashing/hash_map.md +++ b/docs-en/chapter_hashing/hash_map.md @@ -983,13 +983,11 @@ The following code implements a simple hash table. Here, we encapsulate `key` an /* 基于数组实现的哈希表 */ class ArrayHashMap { - private var buckets: [Pair?] = [] + private var buckets: [Pair?] init() { // 初始化数组,包含 100 个桶 - for _ in 0 ..< 100 { - buckets.append(nil) - } + buckets = Array(repeating: nil, count: 100) } /* 哈希函数 */ @@ -1021,35 +1019,17 @@ The following code implements a simple hash table. Here, we encapsulate `key` an /* 获取所有键值对 */ func pairSet() -> [Pair] { - var pairSet: [Pair] = [] - for pair in buckets { - if let pair = pair { - pairSet.append(pair) - } - } - return pairSet + buckets.compactMap { $0 } } /* 获取所有键 */ func keySet() -> [Int] { - var keySet: [Int] = [] - for pair in buckets { - if let pair = pair { - keySet.append(pair.key) - } - } - return keySet + buckets.compactMap { $0?.key } } /* 获取所有值 */ func valueSet() -> [String] { - var valueSet: [String] = [] - for pair in buckets { - if let pair = pair { - valueSet.append(pair.val) - } - } - return valueSet + buckets.compactMap { $0?.val } } /* 打印哈希表 */ diff --git a/docs-en/chapter_stack_and_queue/deque.md b/docs-en/chapter_stack_and_queue/deque.md index 7a32f5d79..2cffb54c3 100644 --- a/docs-en/chapter_stack_and_queue/deque.md +++ b/docs-en/chapter_stack_and_queue/deque.md @@ -999,15 +999,15 @@ The implementation code is as follows: class LinkedListDeque { private var front: ListNode? // 头节点 front private var rear: ListNode? // 尾节点 rear - private var queSize: Int // 双向队列的长度 + private var _size: Int // 双向队列的长度 init() { - queSize = 0 + _size = 0 } /* 获取双向队列的长度 */ func size() -> Int { - queSize + _size } /* 判断双向队列是否为空 */ @@ -1037,7 +1037,7 @@ The implementation code is as follows: node.prev = rear rear = node // 更新尾节点 } - queSize += 1 // 更新队列长度 + _size += 1 // 更新队列长度 } /* 队首入队 */ @@ -1078,7 +1078,7 @@ The implementation code is as follows: } rear = rPrev // 更新尾节点 } - queSize -= 1 // 更新队列长度 + _size -= 1 // 更新队列长度 return val } @@ -1093,13 +1093,19 @@ The implementation code is as follows: } /* 访问队首元素 */ - func peekFirst() -> Int? { - isEmpty() ? nil : front?.val + func peekFirst() -> Int { + if isEmpty() { + fatalError("双向队列为空") + } + return front!.val } /* 访问队尾元素 */ - func peekLast() -> Int? { - isEmpty() ? nil : rear?.val + func peekLast() -> Int { + if isEmpty() { + fatalError("双向队列为空") + } + return rear!.val } /* 返回数组用于打印 */ diff --git a/docs-en/chapter_stack_and_queue/queue.md b/docs-en/chapter_stack_and_queue/queue.md index cf360f9ad..f4fdf94c6 100755 --- a/docs-en/chapter_stack_and_queue/queue.md +++ b/docs-en/chapter_stack_and_queue/queue.md @@ -684,9 +684,11 @@ Below is the code for implementing a queue using a linked list: class LinkedListQueue { private var front: ListNode? // 头节点 private var rear: ListNode? // 尾节点 - private var _size = 0 + private var _size: Int - init() {} + init() { + _size = 0 + } /* 获取队列的长度 */ func size() -> Int { @@ -1605,12 +1607,14 @@ In a circular array, `front` or `rear` needs to loop back to the start of the ar /* 基于环形数组实现的队列 */ class ArrayQueue { private var nums: [Int] // 用于存储队列元素的数组 - private var front = 0 // 队首指针,指向队首元素 - private var queSize = 0 // 队列长度 + private var front: Int // 队首指针,指向队首元素 + private var _size: Int // 队列长度 init(capacity: Int) { // 初始化数组 nums = Array(repeating: 0, count: capacity) + front = 0 + _size = 0 } /* 获取队列的容量 */ @@ -1620,12 +1624,12 @@ In a circular array, `front` or `rear` needs to loop back to the start of the ar /* 获取队列的长度 */ func size() -> Int { - queSize + _size } /* 判断队列是否为空 */ func isEmpty() -> Bool { - queSize == 0 + size() == 0 } /* 入队 */ @@ -1636,10 +1640,10 @@ In a circular array, `front` or `rear` needs to loop back to the start of the ar } // 计算队尾指针,指向队尾索引 + 1 // 通过取余操作实现 rear 越过数组尾部后回到头部 - let rear = (front + queSize) % capacity() + let rear = (front + size()) % capacity() // 将 num 添加至队尾 nums[rear] = num - queSize += 1 + _size += 1 } /* 出队 */ @@ -1648,7 +1652,7 @@ In a circular array, `front` or `rear` needs to loop back to the start of the ar let num = peek() // 队首指针向后移动一位,若越过尾部,则返回到数组头部 front = (front + 1) % capacity() - queSize -= 1 + _size -= 1 return num } @@ -1663,11 +1667,7 @@ In a circular array, `front` or `rear` needs to loop back to the start of the ar /* 返回数组 */ func toArray() -> [Int] { // 仅转换有效长度范围内的列表元素 - var res = Array(repeating: 0, count: queSize) - for (i, j) in sequence(first: (0, front), next: { $0 < self.queSize - 1 ? ($0 + 1, $1 + 1) : nil }) { - res[i] = nums[j % capacity()] - } - return res + (front ..< front + size()).map { nums[$0 % capacity()] } } } ``` diff --git a/docs-en/chapter_stack_and_queue/stack.md b/docs-en/chapter_stack_and_queue/stack.md index 6b79c2601..db50d987b 100755 --- a/docs-en/chapter_stack_and_queue/stack.md +++ b/docs-en/chapter_stack_and_queue/stack.md @@ -643,9 +643,11 @@ Below is an example code for implementing a stack based on a linked list: /* 基于链表实现的栈 */ class LinkedListStack { private var _peek: ListNode? // 将头节点作为栈顶 - private var _size = 0 // 栈的长度 + private var _size: Int // 栈的长度 - init() {} + init() { + _size = 0 + } /* 获取栈的长度 */ func size() -> Int { @@ -685,8 +687,8 @@ Below is an example code for implementing a stack based on a linked list: /* 将 List 转化为 Array 并返回 */ func toArray() -> [Int] { var node = _peek - var res = Array(repeating: 0, count: _size) - for i in sequence(first: res.count - 1, next: { $0 >= 0 + 1 ? $0 - 1 : nil }) { + var res = Array(repeating: 0, count: size()) + for i in res.indices.reversed() { res[i] = node!.val node = node?.next } diff --git a/docs/chapter_appendix/terminology.md b/docs/chapter_appendix/terminology.md index 3ff5170b6..eaa1cfd42 100644 --- a/docs/chapter_appendix/terminology.md +++ b/docs/chapter_appendix/terminology.md @@ -6,8 +6,8 @@ comments: true 表 16-1 列出了书中出现的重要术语,值得注意以下几点。 -- 部分名词在简体中文和繁体中文下的叫法不同。 - 建议记住名词的英文叫法,以便阅读英文文献。 +- 部分名词在简体中文和繁体中文下的叫法不同。

表 16-1   数据结构与算法的重要名词

@@ -15,11 +15,16 @@ comments: true | English | 简体中文 | 繁体中文 | | ------------------------------ | -------------- | -------------- | -| algorithm | 算法 | 算法 | +| algorithm | 算法 | 演算法 | | data structure | 数据结构 | 資料結構 | +| code | 代码 | 程式碼 | +| function | 函数 | 函式 | +| method | 方法 | 方法 | +| variable | 变量 | 變數 | | asymptotic complexity analysis | 渐近复杂度分析 | 漸近複雜度分析 | | time complexity | 时间复杂度 | 時間複雜度 | | space complexity | 空间复杂度 | 空間複雜度 | +| loop | 循环 | 迴圈 | | iteration | 迭代 | 迭代 | | recursion | 递归 | 遞迴 | | tail recursion | 尾递归 | 尾遞迴 | @@ -31,8 +36,8 @@ comments: true | 2’s complement | 补码 | 補碼 | | array | 数组 | 陣列 | | index | 索引 | 索引 | -| linked list | 链表 | 連結串列 | -| linked list node, list node | 链表节点 | 連結串列節點 | +| linked list | 链表 | 鏈結串列 | +| linked list node, list node | 链表节点 | 鏈結串列節點 | | head node | 头节点 | 頭節點 | | tail node | 尾节点 | 尾節點 | | list | 列表 | 列表 | @@ -76,7 +81,7 @@ comments: true | complete binary tree | 完全二叉树 | 完全二元樹 | | full binary tree | 完满二叉树 | 完滿二元樹 | | balanced binary tree | 平衡二叉树 | 平衡二元樹 | -| AVL tree | AVL 树 | AVL 樹 | +| AVL tree | AVL 树 | AVL 樹 | | red-black tree | 红黑树 | 紅黑樹 | | level-order traversal | 层序遍历 | 層序走訪 | | breadth-first traversal | 广度优先遍历 | 廣度優先走訪 | @@ -84,12 +89,12 @@ comments: true | binary search tree | 二叉搜索树 | 二元搜尋樹 | | balanced binary search tree | 平衡二叉搜索树 | 平衡二元搜尋樹 | | balance factor | 平衡因子 | 平衡因子 | -| heap | 堆 | 堆 | -| max heap | 大顶堆 | 大頂堆 | -| min heap | 小顶堆 | 小頂堆 | +| heap | 堆 | 堆積 | +| max heap | 大顶堆 | 大頂堆積 | +| min heap | 小顶堆 | 小頂堆積 | | priority queue | 优先队列 | 優先佇列 | -| heapify | 堆化 | 堆化 | -| top-$k$ problem | Top-$k$ 问题 | Top-$k$ 問題 | +| heapify | 堆化 | 堆積化 | +| top-$k$ problem | Top-$k$ 问题 | Top-$k$ 問題 | | graph | 图 | 圖 | | vertex | 顶点 | 頂點 | | undirected graph | 无向图 | 無向圖 | @@ -113,12 +118,12 @@ comments: true | insertion sort | 插入排序 | 插入排序 | | quick sort | 快速排序 | 快速排序 | | merge sort | 归并排序 | 合併排序 | -| heap sort | 堆排序 | 堆排序 | +| heap sort | 堆排序 | 堆積排序 | | bucket sort | 桶排序 | 桶排序 | | counting sort | 计数排序 | 計數排序 | | radix sort | 基数排序 | 基數排序 | | divide and conquer | 分治 | 分治 | -| hanota problem | 汉诺塔问题 | 漢諾塔問題 | +| hanota problem | 汉诺塔问题 | 河內塔問題 | | backtracking algorithm | 回溯算法 | 回溯演算法 | | constraint | 约束 | 約束 | | solution | 解 | 解 | @@ -132,6 +137,6 @@ comments: true | state-trasition equation | 状态转移方程 | 狀態轉移方程 | | knapsack problem | 背包问题 | 背包問題 | | edit distance problem | 编辑距离问题 | 編輯距離問題 | -| greedy algorithm | 贪心算法 | 貪心演算法 | +| greedy algorithm | 贪心算法 | 貪婪演算法 | diff --git a/docs/chapter_array_and_linkedlist/array.md b/docs/chapter_array_and_linkedlist/array.md index a8082e560..847ee1fd9 100755 --- a/docs/chapter_array_and_linkedlist/array.md +++ b/docs/chapter_array_and_linkedlist/array.md @@ -750,6 +750,11 @@ comments: true for num in nums { count += num } + // 同时遍历数据索引和元素 + for (i, num) in nums.enumerated() { + count += nums[i] + count += num + } } ``` diff --git a/docs/chapter_array_and_linkedlist/linked_list.md b/docs/chapter_array_and_linkedlist/linked_list.md index 16964d6b5..7abb6be58 100755 --- a/docs/chapter_array_and_linkedlist/linked_list.md +++ b/docs/chapter_array_and_linkedlist/linked_list.md @@ -644,7 +644,6 @@ comments: true let P = n0.next let n1 = P?.next n0.next = n1 - P?.next = nil } ``` diff --git a/docs/chapter_array_and_linkedlist/list.md b/docs/chapter_array_and_linkedlist/list.md index 62e41e569..fc0efcaf8 100755 --- a/docs/chapter_array_and_linkedlist/list.md +++ b/docs/chapter_array_and_linkedlist/list.md @@ -1412,12 +1412,15 @@ comments: true /* 列表类 */ class MyList { private var arr: [Int] // 数组(存储列表元素) - private var _capacity = 10 // 列表容量 - private var _size = 0 // 列表长度(当前元素数量) - private let extendRatio = 2 // 每次列表扩容的倍数 + private var _capacity: Int // 列表容量 + private var _size: Int // 列表长度(当前元素数量) + private let extendRatio: Int // 每次列表扩容的倍数 /* 构造方法 */ init() { + _capacity = 10 + _size = 0 + extendRatio = 2 arr = Array(repeating: 0, count: _capacity) } @@ -1434,7 +1437,7 @@ comments: true /* 访问元素 */ func get(index: Int) -> Int { // 索引如果越界则抛出错误,下同 - if index < 0 || index >= _size { + if index < 0 || index >= size() { fatalError("索引越界") } return arr[index] @@ -1442,7 +1445,7 @@ comments: true /* 更新元素 */ func set(index: Int, num: Int) { - if index < 0 || index >= _size { + if index < 0 || index >= size() { fatalError("索引越界") } arr[index] = num @@ -1451,25 +1454,25 @@ comments: true /* 在尾部添加元素 */ func add(num: Int) { // 元素数量超出容量时,触发扩容机制 - if _size == _capacity { + if size() == capacity() { extendCapacity() } - arr[_size] = num + arr[size()] = num // 更新元素数量 _size += 1 } /* 在中间插入元素 */ func insert(index: Int, num: Int) { - if index < 0 || index >= _size { + if index < 0 || index >= size() { fatalError("索引越界") } // 元素数量超出容量时,触发扩容机制 - if _size == _capacity { + if size() == capacity() { extendCapacity() } // 将索引 index 以及之后的元素都向后移动一位 - for j in sequence(first: _size - 1, next: { $0 >= index + 1 ? $0 - 1 : nil }) { + for j in (index ..< size()).reversed() { arr[j + 1] = arr[j] } arr[index] = num @@ -1480,12 +1483,12 @@ comments: true /* 删除元素 */ @discardableResult func remove(index: Int) -> Int { - if index < 0 || index >= _size { + if index < 0 || index >= size() { fatalError("索引越界") } let num = arr[index] // 将将索引 index 之后的元素都向前移动一位 - for j in index ..< (_size - 1) { + for j in index ..< (size() - 1) { arr[j] = arr[j + 1] } // 更新元素数量 @@ -1497,18 +1500,14 @@ comments: true /* 列表扩容 */ func extendCapacity() { // 新建一个长度为原数组 extendRatio 倍的新数组,并将原数组复制到新数组 - arr = arr + Array(repeating: 0, count: _capacity * (extendRatio - 1)) + arr = arr + Array(repeating: 0, count: capacity() * (extendRatio - 1)) // 更新列表容量 _capacity = arr.count } /* 将列表转换为数组 */ func toArray() -> [Int] { - var arr = Array(repeating: 0, count: _size) - for i in 0 ..< _size { - arr[i] = get(index: i) - } - return arr + Array(arr.prefix(size())) } } ``` diff --git a/docs/chapter_backtracking/subset_sum_problem.md b/docs/chapter_backtracking/subset_sum_problem.md index d41a5792f..5512b96db 100644 --- a/docs/chapter_backtracking/subset_sum_problem.md +++ b/docs/chapter_backtracking/subset_sum_problem.md @@ -209,7 +209,7 @@ comments: true return } // 遍历所有选择 - for i in stride(from: 0, to: choices.count, by: 1) { + for i in choices.indices { // 剪枝:若子集和超过 target ,则跳过该选择 if total + choices[i] > target { continue @@ -680,7 +680,7 @@ comments: true } // 遍历所有选择 // 剪枝二:从 start 开始遍历,避免生成重复子集 - for i in stride(from: start, to: choices.count, by: 1) { + for i in choices.indices.dropFirst(start) { // 剪枝一:若子集和超过 target ,则直接结束循环 // 这是因为数组已排序,后边元素更大,子集和一定超过 target if target - choices[i] < 0 { @@ -1181,7 +1181,7 @@ comments: true // 遍历所有选择 // 剪枝二:从 start 开始遍历,避免生成重复子集 // 剪枝三:从 start 开始遍历,避免重复选择同一元素 - for i in stride(from: start, to: choices.count, by: 1) { + for i in choices.indices.dropFirst(start) { // 剪枝一:若子集和超过 target ,则直接结束循环 // 这是因为数组已排序,后边元素更大,子集和一定超过 target if target - choices[i] < 0 { diff --git a/docs/chapter_computational_complexity/iteration_and_recursion.md b/docs/chapter_computational_complexity/iteration_and_recursion.md index 6947dcbc7..7bf08dc5e 100644 --- a/docs/chapter_computational_complexity/iteration_and_recursion.md +++ b/docs/chapter_computational_complexity/iteration_and_recursion.md @@ -1631,7 +1631,7 @@ comments: true var stack: [Int] = [] var res = 0 // 递:递归调用 - for i in stride(from: n, to: 0, by: -1) { + for i in (1 ... n).reversed() { // 通过“入栈操作”模拟“递” stack.append(i) } diff --git a/docs/chapter_computational_complexity/time_complexity.md b/docs/chapter_computational_complexity/time_complexity.md index 95bb2ab3c..8340f0a71 100755 --- a/docs/chapter_computational_complexity/time_complexity.md +++ b/docs/chapter_computational_complexity/time_complexity.md @@ -321,7 +321,7 @@ $$ // 算法 C 的时间复杂度:常数阶 func algorithmC(n: Int) { - for _ in 0 ..< 1000000 { + for _ in 0 ..< 1_000_000 { print(0) } } @@ -1784,7 +1784,7 @@ $$ func bubbleSort(nums: inout [Int]) -> Int { var count = 0 // 计数器 // 外循环:未排序区间为 [0, i] - for i in stride(from: nums.count - 1, to: 0, by: -1) { + for i in nums.indices.dropFirst().reversed() { // 内循环:将未排序区间 [0, i] 中的最大元素交换至该区间的最右端 for j in 0 ..< i { if nums[j] > nums[j + 1] { diff --git a/docs/chapter_data_structure/basic_data_types.md b/docs/chapter_data_structure/basic_data_types.md index 652a1e375..16b4e7ba1 100644 --- a/docs/chapter_data_structure/basic_data_types.md +++ b/docs/chapter_data_structure/basic_data_types.md @@ -109,10 +109,10 @@ comments: true ```swift title="" // 使用多种基本数据类型来初始化数组 - let numbers = Array(repeating: Int(), count: 5) - let decimals = Array(repeating: Double(), count: 5) - let characters = Array(repeating: Character("a"), count: 5) - let bools = Array(repeating: Bool(), count: 5) + let numbers = Array(repeating: 0, count: 5) + let decimals = Array(repeating: 0.0, count: 5) + let characters: [Character] = Array(repeating: "a", count: 5) + let bools = Array(repeating: false, count: 5) ``` === "JS" diff --git a/docs/chapter_divide_and_conquer/binary_search_recur.md b/docs/chapter_divide_and_conquer/binary_search_recur.md index bb0545acd..ed8c5f252 100644 --- a/docs/chapter_divide_and_conquer/binary_search_recur.md +++ b/docs/chapter_divide_and_conquer/binary_search_recur.md @@ -224,9 +224,8 @@ comments: true /* 二分查找 */ func binarySearch(nums: [Int], target: Int) -> Int { - let n = nums.count // 求解问题 f(0, n-1) - return dfs(nums: nums, target: target, i: 0, j: n - 1) + dfs(nums: nums, target: target, i: nums.startIndex, j: nums.endIndex - 1) } ``` diff --git a/docs/chapter_divide_and_conquer/build_binary_tree_problem.md b/docs/chapter_divide_and_conquer/build_binary_tree_problem.md index b6bb81582..4ed9a14b5 100644 --- a/docs/chapter_divide_and_conquer/build_binary_tree_problem.md +++ b/docs/chapter_divide_and_conquer/build_binary_tree_problem.md @@ -259,7 +259,7 @@ comments: true func buildTree(preorder: [Int], inorder: [Int]) -> TreeNode? { // 初始化哈希表,存储 inorder 元素到索引的映射 let inorderMap = inorder.enumerated().reduce(into: [:]) { $0[$1.element] = $1.offset } - return dfs(preorder: preorder, inorderMap: inorderMap, i: 0, l: 0, r: inorder.count - 1) + return dfs(preorder: preorder, inorderMap: inorderMap, i: inorder.startIndex, l: inorder.startIndex, r: inorder.endIndex - 1) } ``` diff --git a/docs/chapter_dynamic_programming/dp_problem_features.md b/docs/chapter_dynamic_programming/dp_problem_features.md index 264231946..aab06321b 100644 --- a/docs/chapter_dynamic_programming/dp_problem_features.md +++ b/docs/chapter_dynamic_programming/dp_problem_features.md @@ -164,7 +164,7 @@ $$ dp[1] = cost[1] dp[2] = cost[2] // 状态转移:从较小子问题逐步求解较大子问题 - for i in stride(from: 3, through: n, by: 1) { + for i in 3 ... n { dp[i] = min(dp[i - 1], dp[i - 2]) + cost[i] } return dp[n] @@ -421,7 +421,7 @@ $$ return cost[n] } var (a, b) = (cost[1], cost[2]) - for i in stride(from: 3, through: n, by: 1) { + for i in 3 ... n { (a, b) = (b, min(a, b) + cost[i]) } return b @@ -721,7 +721,7 @@ $$ dp[2][1] = 0 dp[2][2] = 1 // 状态转移:从较小子问题逐步求解较大子问题 - for i in stride(from: 3, through: n, by: 1) { + for i in 3 ... n { dp[i][1] = dp[i - 1][2] dp[i][2] = dp[i - 2][1] + dp[i - 2][2] } diff --git a/docs/chapter_dynamic_programming/dp_solution_pipeline.md b/docs/chapter_dynamic_programming/dp_solution_pipeline.md index f665d1a06..8db036484 100644 --- a/docs/chapter_dynamic_programming/dp_solution_pipeline.md +++ b/docs/chapter_dynamic_programming/dp_solution_pipeline.md @@ -861,16 +861,16 @@ $$ var dp = Array(repeating: Array(repeating: 0, count: m), count: n) dp[0][0] = grid[0][0] // 状态转移:首行 - for j in stride(from: 1, to: m, by: 1) { + for j in 1 ..< m { dp[0][j] = dp[0][j - 1] + grid[0][j] } // 状态转移:首列 - for i in stride(from: 1, to: n, by: 1) { + for i in 1 ..< n { dp[i][0] = dp[i - 1][0] + grid[i][0] } // 状态转移:其余行和列 - for i in stride(from: 1, to: n, by: 1) { - for j in stride(from: 1, to: m, by: 1) { + for i in 1 ..< n { + for j in 1 ..< m { dp[i][j] = min(dp[i][j - 1], dp[i - 1][j]) + grid[i][j] } } @@ -1244,15 +1244,15 @@ $$ var dp = Array(repeating: 0, count: m) // 状态转移:首行 dp[0] = grid[0][0] - for j in stride(from: 1, to: m, by: 1) { + for j in 1 ..< m { dp[j] = dp[j - 1] + grid[0][j] } // 状态转移:其余行 - for i in stride(from: 1, to: n, by: 1) { + for i in 1 ..< n { // 状态转移:首列 dp[0] = dp[0] + grid[i][0] // 状态转移:其余列 - for j in stride(from: 1, to: m, by: 1) { + for j in 1 ..< m { dp[j] = min(dp[j - 1], dp[j]) + grid[i][j] } } diff --git a/docs/chapter_dynamic_programming/edit_distance_problem.md b/docs/chapter_dynamic_programming/edit_distance_problem.md index a760d2d67..560c7009f 100644 --- a/docs/chapter_dynamic_programming/edit_distance_problem.md +++ b/docs/chapter_dynamic_programming/edit_distance_problem.md @@ -234,15 +234,15 @@ $$ let m = t.utf8CString.count var dp = Array(repeating: Array(repeating: 0, count: m + 1), count: n + 1) // 状态转移:首行首列 - for i in stride(from: 1, through: n, by: 1) { + for i in 1 ... n { dp[i][0] = i } - for j in stride(from: 1, through: m, by: 1) { + for j in 1 ... m { dp[0][j] = j } // 状态转移:其余行和列 - for i in stride(from: 1, through: n, by: 1) { - for j in stride(from: 1, through: m, by: 1) { + for i in 1 ... n { + for j in 1 ... m { if s.utf8CString[i - 1] == t.utf8CString[j - 1] { // 若两字符相等,则直接跳过此两字符 dp[i][j] = dp[i - 1][j - 1] @@ -681,16 +681,16 @@ $$ let m = t.utf8CString.count var dp = Array(repeating: 0, count: m + 1) // 状态转移:首行 - for j in stride(from: 1, through: m, by: 1) { + for j in 1 ... m { dp[j] = j } // 状态转移:其余行 - for i in stride(from: 1, through: n, by: 1) { + for i in 1 ... n { // 状态转移:首列 var leftup = dp[0] // 暂存 dp[i-1, j-1] dp[0] = i // 状态转移:其余列 - for j in stride(from: 1, through: m, by: 1) { + for j in 1 ... m { let temp = dp[j] if s.utf8CString[i - 1] == t.utf8CString[j - 1] { // 若两字符相等,则直接跳过此两字符 diff --git a/docs/chapter_dynamic_programming/intro_to_dynamic_programming.md b/docs/chapter_dynamic_programming/intro_to_dynamic_programming.md index 74f6ac2f3..a20e33042 100644 --- a/docs/chapter_dynamic_programming/intro_to_dynamic_programming.md +++ b/docs/chapter_dynamic_programming/intro_to_dynamic_programming.md @@ -1126,7 +1126,7 @@ $$ dp[1] = 1 dp[2] = 2 // 状态转移:从较小子问题逐步求解较大子问题 - for i in stride(from: 3, through: n, by: 1) { + for i in 3 ... n { dp[i] = dp[i - 1] + dp[i - 2] } return dp[n] @@ -1370,7 +1370,7 @@ $$ } var a = 1 var b = 2 - for _ in stride(from: 3, through: n, by: 1) { + for _ in 3 ... n { (a, b) = (b, a + b) } return b diff --git a/docs/chapter_dynamic_programming/knapsack_problem.md b/docs/chapter_dynamic_programming/knapsack_problem.md index 830dcdcdc..58f825393 100644 --- a/docs/chapter_dynamic_programming/knapsack_problem.md +++ b/docs/chapter_dynamic_programming/knapsack_problem.md @@ -802,8 +802,8 @@ $$ // 初始化 dp 表 var dp = Array(repeating: Array(repeating: 0, count: cap + 1), count: n + 1) // 状态转移 - for i in stride(from: 1, through: n, by: 1) { - for c in stride(from: 1, through: cap, by: 1) { + for i in 1 ... n { + for c in 1 ... cap { if wgt[i - 1] > c { // 若超过背包容量,则不选物品 i dp[i][c] = dp[i - 1][c] @@ -1191,9 +1191,9 @@ $$ // 初始化 dp 表 var dp = Array(repeating: 0, count: cap + 1) // 状态转移 - for i in stride(from: 1, through: n, by: 1) { + for i in 1 ... n { // 倒序遍历 - for c in stride(from: cap, through: 1, by: -1) { + for c in (1 ... cap).reversed() { if wgt[i - 1] <= c { // 不选和选物品 i 这两种方案的较大值 dp[c] = max(dp[c], dp[c - wgt[i - 1]] + val[i - 1]) diff --git a/docs/chapter_dynamic_programming/unbounded_knapsack_problem.md b/docs/chapter_dynamic_programming/unbounded_knapsack_problem.md index 7e8d6c017..aae7dd99f 100644 --- a/docs/chapter_dynamic_programming/unbounded_knapsack_problem.md +++ b/docs/chapter_dynamic_programming/unbounded_knapsack_problem.md @@ -166,8 +166,8 @@ $$ // 初始化 dp 表 var dp = Array(repeating: Array(repeating: 0, count: cap + 1), count: n + 1) // 状态转移 - for i in stride(from: 1, through: n, by: 1) { - for c in stride(from: 1, through: cap, by: 1) { + for i in 1 ... n { + for c in 1 ... cap { if wgt[i - 1] > c { // 若超过背包容量,则不选物品 i dp[i][c] = dp[i - 1][c] @@ -506,8 +506,8 @@ $$ // 初始化 dp 表 var dp = Array(repeating: 0, count: cap + 1) // 状态转移 - for i in stride(from: 1, through: n, by: 1) { - for c in stride(from: 1, through: cap, by: 1) { + for i in 1 ... n { + for c in 1 ... cap { if wgt[i - 1] > c { // 若超过背包容量,则不选物品 i dp[c] = dp[c] @@ -882,12 +882,12 @@ $$ // 初始化 dp 表 var dp = Array(repeating: Array(repeating: 0, count: amt + 1), count: n + 1) // 状态转移:首行首列 - for a in stride(from: 1, through: amt, by: 1) { + for a in 1 ... amt { dp[0][a] = MAX } // 状态转移:其余行和列 - for i in stride(from: 1, through: n, by: 1) { - for a in stride(from: 1, through: amt, by: 1) { + for i in 1 ... n { + for a in 1 ... amt { if coins[i - 1] > a { // 若超过目标金额,则不选硬币 i dp[i][a] = dp[i - 1][a] @@ -1300,8 +1300,8 @@ $$ var dp = Array(repeating: MAX, count: amt + 1) dp[0] = 0 // 状态转移 - for i in stride(from: 1, through: n, by: 1) { - for a in stride(from: 1, through: amt, by: 1) { + for i in 1 ... n { + for a in 1 ... amt { if coins[i - 1] > a { // 若超过目标金额,则不选硬币 i dp[a] = dp[a] @@ -1660,12 +1660,12 @@ $$ // 初始化 dp 表 var dp = Array(repeating: Array(repeating: 0, count: amt + 1), count: n + 1) // 初始化首列 - for i in stride(from: 0, through: n, by: 1) { + for i in 0 ... n { dp[i][0] = 1 } // 状态转移 - for i in stride(from: 1, through: n, by: 1) { - for a in stride(from: 1, through: amt, by: 1) { + for i in 1 ... n { + for a in 1 ... amt { if coins[i - 1] > a { // 若超过目标金额,则不选硬币 i dp[i][a] = dp[i - 1][a] @@ -2002,8 +2002,8 @@ $$ var dp = Array(repeating: 0, count: amt + 1) dp[0] = 1 // 状态转移 - for i in stride(from: 1, through: n, by: 1) { - for a in stride(from: 1, through: amt, by: 1) { + for i in 1 ... n { + for a in 1 ... amt { if coins[i - 1] > a { // 若超过目标金额,则不选硬币 i dp[a] = dp[a] diff --git a/docs/chapter_graph/graph_operations.md b/docs/chapter_graph/graph_operations.md index 6cee05db1..f6079aefd 100644 --- a/docs/chapter_graph/graph_operations.md +++ b/docs/chapter_graph/graph_operations.md @@ -1512,8 +1512,8 @@ comments: true fatalError("参数错误") } // 删除边 vet1 - vet2 - adjList[vet1]?.removeAll(where: { $0 == vet2 }) - adjList[vet2]?.removeAll(where: { $0 == vet1 }) + adjList[vet1]?.removeAll { $0 == vet2 } + adjList[vet2]?.removeAll { $0 == vet1 } } /* 添加顶点 */ @@ -1534,19 +1534,16 @@ comments: true adjList.removeValue(forKey: vet) // 遍历其他顶点的链表,删除所有包含 vet 的边 for key in adjList.keys { - adjList[key]?.removeAll(where: { $0 == vet }) + adjList[key]?.removeAll { $0 == vet } } } /* 打印邻接表 */ public func print() { Swift.print("邻接表 =") - for pair in adjList { - var tmp: [Int] = [] - for vertex in pair.value { - tmp.append(vertex.val) - } - Swift.print("\(pair.key.val): \(tmp),") + for (vertex, list) in adjList { + let list = list.map { $0.val } + Swift.print("\(vertex.val): \(list),") } } } diff --git a/docs/chapter_greedy/fractional_knapsack_problem.md b/docs/chapter_greedy/fractional_knapsack_problem.md index 74c924c43..57736823d 100644 --- a/docs/chapter_greedy/fractional_knapsack_problem.md +++ b/docs/chapter_greedy/fractional_knapsack_problem.md @@ -244,7 +244,7 @@ comments: true // 创建物品列表,包含两个属性:重量、价值 var items = zip(wgt, val).map { Item(w: $0, v: $1) } // 按照单位价值 item.v / item.w 从高到低进行排序 - items.sort(by: { -(Double($0.v) / Double($0.w)) < -(Double($1.v) / Double($1.w)) }) + items.sort { -(Double($0.v) / Double($0.w)) < -(Double($1.v) / Double($1.w)) } // 循环贪心选择 var res = 0.0 var cap = cap diff --git a/docs/chapter_greedy/max_capacity_problem.md b/docs/chapter_greedy/max_capacity_problem.md index 13f80ac58..e1b20759f 100644 --- a/docs/chapter_greedy/max_capacity_problem.md +++ b/docs/chapter_greedy/max_capacity_problem.md @@ -220,7 +220,7 @@ $$ /* 最大容量:贪心 */ func maxCapacity(ht: [Int]) -> Int { // 初始化 i, j,使其分列数组两端 - var i = 0, j = ht.count - 1 + var i = ht.startIndex, j = ht.endIndex - 1 // 初始最大容量为 0 var res = 0 // 循环贪心选择,直至两板相遇 diff --git a/docs/chapter_hashing/hash_collision.md b/docs/chapter_hashing/hash_collision.md index bd7d37ed5..208f93bc8 100644 --- a/docs/chapter_hashing/hash_collision.md +++ b/docs/chapter_hashing/hash_collision.md @@ -618,7 +618,7 @@ comments: true /* 负载因子 */ func loadFactor() -> Double { - Double(size / capacity) + Double(size) / Double(capacity) } /* 查询操作 */ @@ -664,9 +664,10 @@ comments: true for (pairIndex, pair) in bucket.enumerated() { if pair.key == key { buckets[index].remove(at: pairIndex) + size -= 1 + break } } - size -= 1 } /* 扩容哈希表 */ @@ -2004,7 +2005,7 @@ comments: true /* 负载因子 */ func loadFactor() -> Double { - Double(size / capacity) + Double(size) / Double(capacity) } /* 搜索 key 对应的桶索引 */ diff --git a/docs/chapter_hashing/hash_map.md b/docs/chapter_hashing/hash_map.md index 1b2648bee..7b5be4185 100755 --- a/docs/chapter_hashing/hash_map.md +++ b/docs/chapter_hashing/hash_map.md @@ -983,13 +983,11 @@ index = hash(key) % capacity /* 基于数组实现的哈希表 */ class ArrayHashMap { - private var buckets: [Pair?] = [] + private var buckets: [Pair?] init() { // 初始化数组,包含 100 个桶 - for _ in 0 ..< 100 { - buckets.append(nil) - } + buckets = Array(repeating: nil, count: 100) } /* 哈希函数 */ @@ -1021,35 +1019,17 @@ index = hash(key) % capacity /* 获取所有键值对 */ func pairSet() -> [Pair] { - var pairSet: [Pair] = [] - for pair in buckets { - if let pair = pair { - pairSet.append(pair) - } - } - return pairSet + buckets.compactMap { $0 } } /* 获取所有键 */ func keySet() -> [Int] { - var keySet: [Int] = [] - for pair in buckets { - if let pair = pair { - keySet.append(pair.key) - } - } - return keySet + buckets.compactMap { $0?.key } } /* 获取所有值 */ func valueSet() -> [String] { - var valueSet: [String] = [] - for pair in buckets { - if let pair = pair { - valueSet.append(pair.val) - } - } - return valueSet + buckets.compactMap { $0?.val } } /* 打印哈希表 */ diff --git a/docs/chapter_heap/build_heap.md b/docs/chapter_heap/build_heap.md index bc28789c6..3539c07a5 100644 --- a/docs/chapter_heap/build_heap.md +++ b/docs/chapter_heap/build_heap.md @@ -105,7 +105,7 @@ comments: true // 将列表元素原封不动添加进堆 maxHeap = nums // 堆化除叶节点以外的其他所有节点 - for i in stride(from: parent(i: size() - 1), through: 0, by: -1) { + for i in (0 ... parent(i: size() - 1)).reversed() { siftDown(i: i) } } diff --git a/docs/chapter_heap/heap.md b/docs/chapter_heap/heap.md index d43f3a998..33bf15032 100644 --- a/docs/chapter_heap/heap.md +++ b/docs/chapter_heap/heap.md @@ -280,7 +280,35 @@ comments: true === "Swift" ```swift title="heap.swift" - // Swift 未提供内置 Heap 类 + /* 初始化堆 */ + // Swift 的 Heap 类型同时支持最大堆和最小堆,且需要引入 swift-collections + var heap = Heap() + + /* 元素入堆 */ + heap.insert(1) + heap.insert(3) + heap.insert(2) + heap.insert(5) + heap.insert(4) + + /* 获取堆顶元素 */ + var peek = heap.max()! + + /* 堆顶元素出堆 */ + peek = heap.removeMax() // 5 + peek = heap.removeMax() // 4 + peek = heap.removeMax() // 3 + peek = heap.removeMax() // 2 + peek = heap.removeMax() // 1 + + /* 获取堆大小 */ + let size = heap.count + + /* 判断堆是否为空 */ + let isEmpty = heap.isEmpty + + /* 输入列表并建堆 */ + let heap2 = Heap([1, 3, 2, 5, 4]) ``` === "JS" diff --git a/docs/chapter_heap/top_k.md b/docs/chapter_heap/top_k.md index c1f0bc4dc..0671ac155 100644 --- a/docs/chapter_heap/top_k.md +++ b/docs/chapter_heap/top_k.md @@ -194,7 +194,7 @@ comments: true // 初始化一个小顶堆,并将前 k 个元素建堆 var heap = Heap(nums.prefix(k)) // 从第 k+1 个元素开始,保持堆的长度为 k - for i in stride(from: k, to: nums.count, by: 1) { + for i in nums.indices.dropFirst(k) { // 若当前元素大于堆顶元素,则将堆顶元素出堆、当前元素入堆 if nums[i] > heap.min()! { _ = heap.removeMin() diff --git a/docs/chapter_searching/binary_search.md b/docs/chapter_searching/binary_search.md index 91588c76f..ed76ab8e5 100755 --- a/docs/chapter_searching/binary_search.md +++ b/docs/chapter_searching/binary_search.md @@ -168,8 +168,8 @@ comments: true /* 二分查找(双闭区间) */ func binarySearch(nums: [Int], target: Int) -> Int { // 初始化双闭区间 [0, n-1] ,即 i, j 分别指向数组首元素、尾元素 - var i = 0 - var j = nums.count - 1 + var i = nums.startIndex + var j = nums.endIndex - 1 // 循环,当搜索区间为空时跳出(当 i > j 时为空) while i <= j { let m = i + (j - i) / 2 // 计算中点索引 m @@ -466,8 +466,8 @@ comments: true /* 二分查找(左闭右开区间) */ func binarySearchLCRO(nums: [Int], target: Int) -> Int { // 初始化左闭右开区间 [0, n) ,即 i, j 分别指向数组首元素、尾元素+1 - var i = 0 - var j = nums.count + var i = nums.startIndex + var j = nums.endIndex // 循环,当搜索区间为空时跳出(当 i = j 时为空) while i < j { let m = i + (j - i) / 2 // 计算中点索引 m diff --git a/docs/chapter_searching/binary_search_edge.md b/docs/chapter_searching/binary_search_edge.md index a40825c2d..a722cc647 100644 --- a/docs/chapter_searching/binary_search_edge.md +++ b/docs/chapter_searching/binary_search_edge.md @@ -105,7 +105,7 @@ comments: true // 等价于查找 target 的插入点 let i = binarySearchInsertion(nums: nums, target: target) // 未找到 target ,返回 -1 - if i == nums.count || nums[i] != target { + if i == nums.endIndex || nums[i] != target { return -1 } // 找到 target ,返回索引 i diff --git a/docs/chapter_searching/binary_search_insertion.md b/docs/chapter_searching/binary_search_insertion.md index 6bffb0a0d..651e8754f 100644 --- a/docs/chapter_searching/binary_search_insertion.md +++ b/docs/chapter_searching/binary_search_insertion.md @@ -140,7 +140,9 @@ comments: true ```swift title="binary_search_insertion.swift" /* 二分查找插入点(无重复元素) */ func binarySearchInsertionSimple(nums: [Int], target: Int) -> Int { - var i = 0, j = nums.count - 1 // 初始化双闭区间 [0, n-1] + // 初始化双闭区间 [0, n-1] + var i = nums.startIndex + var j = nums.endIndex - 1 while i <= j { let m = i + (j - i) / 2 // 计算中点索引 m if nums[m] < target { @@ -445,7 +447,9 @@ comments: true ```swift title="binary_search_insertion.swift" /* 二分查找插入点(存在重复元素) */ func binarySearchInsertion(nums: [Int], target: Int) -> Int { - var i = 0, j = nums.count - 1 // 初始化双闭区间 [0, n-1] + // 初始化双闭区间 [0, n-1] + var i = nums.startIndex + var j = nums.endIndex - 1 while i <= j { let m = i + (j - i) / 2 // 计算中点索引 m if nums[m] < target { diff --git a/docs/chapter_sorting/bubble_sort.md b/docs/chapter_sorting/bubble_sort.md index 604b897a5..0123c14b3 100755 --- a/docs/chapter_sorting/bubble_sort.md +++ b/docs/chapter_sorting/bubble_sort.md @@ -142,14 +142,12 @@ comments: true /* 冒泡排序 */ func bubbleSort(nums: inout [Int]) { // 外循环:未排序区间为 [0, i] - for i in stride(from: nums.count - 1, to: 0, by: -1) { + for i in nums.indices.dropFirst().reversed() { // 内循环:将未排序区间 [0, i] 中的最大元素交换至该区间的最右端 - for j in stride(from: 0, to: i, by: 1) { + for j in 0 ..< i { if nums[j] > nums[j + 1] { // 交换 nums[j] 与 nums[j + 1] - let tmp = nums[j] - nums[j] = nums[j + 1] - nums[j + 1] = tmp + nums.swapAt(j, j + 1) } } } @@ -404,14 +402,12 @@ comments: true /* 冒泡排序(标志优化)*/ func bubbleSortWithFlag(nums: inout [Int]) { // 外循环:未排序区间为 [0, i] - for i in stride(from: nums.count - 1, to: 0, by: -1) { + for i in nums.indices.dropFirst().reversed() { var flag = false // 初始化标志位 - for j in stride(from: 0, to: i, by: 1) { + for j in 0 ..< i { if nums[j] > nums[j + 1] { // 交换 nums[j] 与 nums[j + 1] - let tmp = nums[j] - nums[j] = nums[j + 1] - nums[j + 1] = tmp + nums.swapAt(j, j + 1) flag = true // 记录交换元素 } } diff --git a/docs/chapter_sorting/bucket_sort.md b/docs/chapter_sorting/bucket_sort.md index 2d8376fce..828deea8f 100644 --- a/docs/chapter_sorting/bucket_sort.md +++ b/docs/chapter_sorting/bucket_sort.md @@ -203,7 +203,7 @@ comments: true for bucket in buckets { for num in bucket { nums[i] = num - nums.formIndex(after: &i) + i += 1 } } } diff --git a/docs/chapter_sorting/counting_sort.md b/docs/chapter_sorting/counting_sort.md index f7a7c1417..b19ae611a 100644 --- a/docs/chapter_sorting/counting_sort.md +++ b/docs/chapter_sorting/counting_sort.md @@ -169,8 +169,8 @@ comments: true } // 3. 遍历 counter ,将各元素填入原数组 nums var i = 0 - for num in stride(from: 0, to: m + 1, by: 1) { - for _ in stride(from: 0, to: counter[num], by: 1) { + for num in 0 ..< m + 1 { + for _ in 0 ..< counter[num] { nums[i] = num i += 1 } @@ -573,19 +573,19 @@ $$ } // 3. 求 counter 的前缀和,将“出现次数”转换为“尾索引” // 即 counter[num]-1 是 num 在 res 中最后一次出现的索引 - for i in stride(from: 0, to: m, by: 1) { + for i in 0 ..< m { counter[i + 1] += counter[i] } // 4. 倒序遍历 nums ,将各元素填入结果数组 res // 初始化数组 res 用于记录结果 var res = Array(repeating: 0, count: nums.count) - for i in stride(from: nums.count - 1, through: 0, by: -1) { + for i in nums.indices.reversed() { let num = nums[i] res[counter[num] - 1] = num // 将 num 放置到对应索引处 counter[num] -= 1 // 令前缀和自减 1 ,得到下次放置 num 的索引 } // 使用结果数组 res 覆盖原数组 nums - for i in stride(from: 0, to: nums.count, by: 1) { + for i in nums.indices { nums[i] = res[i] } } diff --git a/docs/chapter_sorting/heap_sort.md b/docs/chapter_sorting/heap_sort.md index dd56794d9..6f6e0b5e7 100644 --- a/docs/chapter_sorting/heap_sort.md +++ b/docs/chapter_sorting/heap_sort.md @@ -306,7 +306,7 @@ comments: true siftDown(nums: &nums, n: nums.count, i: i) } // 从堆中提取最大元素,循环 n-1 轮 - for i in stride(from: nums.count - 1, to: 0, by: -1) { + for i in nums.indices.dropFirst().reversed() { // 交换根节点与最右叶节点(交换首元素与尾元素) nums.swapAt(0, i) // 以根节点为起点,从顶至底进行堆化 diff --git a/docs/chapter_sorting/insertion_sort.md b/docs/chapter_sorting/insertion_sort.md index a2669d6d8..145853d83 100755 --- a/docs/chapter_sorting/insertion_sort.md +++ b/docs/chapter_sorting/insertion_sort.md @@ -124,7 +124,7 @@ comments: true /* 插入排序 */ func insertionSort(nums: inout [Int]) { // 外循环:已排序区间为 [0, i-1] - for i in stride(from: 1, to: nums.count, by: 1) { + for i in nums.indices.dropFirst() { let base = nums[i] var j = i - 1 // 内循环:将 base 插入到已排序区间 [0, i-1] 中的正确位置 diff --git a/docs/chapter_sorting/merge_sort.md b/docs/chapter_sorting/merge_sort.md index 9aaaea74b..6a2dcfa9d 100755 --- a/docs/chapter_sorting/merge_sort.md +++ b/docs/chapter_sorting/merge_sort.md @@ -305,12 +305,11 @@ comments: true if nums[i] <= nums[j] { tmp[k] = nums[i] i += 1 - k += 1 } else { tmp[k] = nums[j] j += 1 - k += 1 } + k += 1 } // 将左子数组和右子数组的剩余元素复制到临时数组中 while i <= mid { diff --git a/docs/chapter_sorting/quick_sort.md b/docs/chapter_sorting/quick_sort.md index 3b29f1c90..7f2ce2231 100755 --- a/docs/chapter_sorting/quick_sort.md +++ b/docs/chapter_sorting/quick_sort.md @@ -168,12 +168,7 @@ comments: true === "Swift" ```swift title="quick_sort.swift" - /* 元素交换 */ - func swap(nums: inout [Int], i: Int, j: Int) { - let tmp = nums[i] - nums[i] = nums[j] - nums[j] = tmp - } + [class]{}-[func]{swap} /* 哨兵划分 */ func partition(nums: inout [Int], left: Int, right: Int) -> Int { @@ -187,9 +182,9 @@ comments: true while i < j, nums[i] <= nums[left] { i += 1 // 从左向右找首个大于基准数的元素 } - swap(nums: &nums, i: i, j: j) // 交换这两个元素 + nums.swapAt(i, j) // 交换这两个元素 } - swap(nums: &nums, i: i, j: left) // 将基准数交换至两子数组的分界线 + nums.swapAt(i, left) // 将基准数交换至两子数组的分界线 return i // 返回基准数的索引 } ``` @@ -801,12 +796,12 @@ comments: true let m = nums[mid] let r = nums[right] if (l <= m && m <= r) || (r <= m && m <= l) { - return mid; // m 在 l 和 r 之间 + return mid // m 在 l 和 r 之间 } if (m <= l && l <= r) || (r <= l && l <= m) { - return left; // l 在 m 和 r 之间 + return left // l 在 m 和 r 之间 } - return right; + return right } /* 哨兵划分(三数取中值) */ @@ -814,7 +809,7 @@ comments: true // 选取三个候选元素的中位数 let med = medianThree(nums: nums, left: left, mid: (left + right) / 2, right: right) // 将中位数交换至数组最左端 - swap(nums: &nums, i: left, j: med) + nums.swapAt(left, med) return partition(nums: &nums, left: left, right: right) } ``` diff --git a/docs/chapter_sorting/radix_sort.md b/docs/chapter_sorting/radix_sort.md index 2b9c02087..18a5a792f 100644 --- a/docs/chapter_sorting/radix_sort.md +++ b/docs/chapter_sorting/radix_sort.md @@ -304,7 +304,6 @@ $$ func countingSortDigit(nums: inout [Int], exp: Int) { // 十进制的位范围为 0~9 ,因此需要长度为 10 的桶数组 var counter = Array(repeating: 0, count: 10) - let n = nums.count // 统计 0~9 各数字的出现次数 for i in nums.indices { let d = digit(num: nums[i], exp: exp) // 获取 nums[i] 第 k 位,记为 d @@ -315,8 +314,8 @@ $$ counter[i] += counter[i - 1] } // 倒序遍历,根据桶内统计结果,将各元素填入 res - var res = Array(repeating: 0, count: n) - for i in stride(from: n - 1, through: 0, by: -1) { + var res = Array(repeating: 0, count: nums.count) + for i in nums.indices.reversed() { let d = digit(num: nums[i], exp: exp) let j = counter[d] - 1 // 获取 d 在数组中的索引 j res[j] = nums[i] // 将当前元素填入索引 j diff --git a/docs/chapter_stack_and_queue/deque.md b/docs/chapter_stack_and_queue/deque.md index e6a586f85..6cf95465d 100644 --- a/docs/chapter_stack_and_queue/deque.md +++ b/docs/chapter_stack_and_queue/deque.md @@ -1000,15 +1000,15 @@ comments: true class LinkedListDeque { private var front: ListNode? // 头节点 front private var rear: ListNode? // 尾节点 rear - private var queSize: Int // 双向队列的长度 + private var _size: Int // 双向队列的长度 init() { - queSize = 0 + _size = 0 } /* 获取双向队列的长度 */ func size() -> Int { - queSize + _size } /* 判断双向队列是否为空 */ @@ -1038,7 +1038,7 @@ comments: true node.prev = rear rear = node // 更新尾节点 } - queSize += 1 // 更新队列长度 + _size += 1 // 更新队列长度 } /* 队首入队 */ @@ -1079,7 +1079,7 @@ comments: true } rear = rPrev // 更新尾节点 } - queSize -= 1 // 更新队列长度 + _size -= 1 // 更新队列长度 return val } @@ -1094,13 +1094,19 @@ comments: true } /* 访问队首元素 */ - func peekFirst() -> Int? { - isEmpty() ? nil : front?.val + func peekFirst() -> Int { + if isEmpty() { + fatalError("双向队列为空") + } + return front!.val } /* 访问队尾元素 */ - func peekLast() -> Int? { - isEmpty() ? nil : rear?.val + func peekLast() -> Int { + if isEmpty() { + fatalError("双向队列为空") + } + return rear!.val } /* 返回数组用于打印 */ @@ -2554,13 +2560,13 @@ comments: true class ArrayDeque { private var nums: [Int] // 用于存储双向队列元素的数组 private var front: Int // 队首指针,指向队首元素 - private var queSize: Int // 双向队列长度 + private var _size: Int // 双向队列长度 /* 构造方法 */ init(capacity: Int) { nums = Array(repeating: 0, count: capacity) front = 0 - queSize = 0 + _size = 0 } /* 获取双向队列的容量 */ @@ -2570,7 +2576,7 @@ comments: true /* 获取双向队列的长度 */ func size() -> Int { - queSize + _size } /* 判断双向队列是否为空 */ @@ -2597,7 +2603,7 @@ comments: true front = index(i: front - 1) // 将 num 添加至队首 nums[front] = num - queSize += 1 + _size += 1 } /* 队尾入队 */ @@ -2610,7 +2616,7 @@ comments: true let rear = index(i: front + size()) // 将 num 添加至队尾 nums[rear] = num - queSize += 1 + _size += 1 } /* 队首出队 */ @@ -2618,14 +2624,14 @@ comments: true let num = peekFirst() // 队首指针向后移动一位 front = index(i: front + 1) - queSize -= 1 + _size -= 1 return num } /* 队尾出队 */ func popLast() -> Int { let num = peekLast() - queSize -= 1 + _size -= 1 return num } @@ -2650,11 +2656,7 @@ comments: true /* 返回数组用于打印 */ func toArray() -> [Int] { // 仅转换有效长度范围内的列表元素 - var res = Array(repeating: 0, count: size()) - for (i, j) in sequence(first: (0, front), next: { $0 < self.size() - 1 ? ($0 + 1, $1 + 1) : nil }) { - res[i] = nums[index(i: j)] - } - return res + (front ..< front + size()).map { nums[index(i: $0)] } } } ``` diff --git a/docs/chapter_stack_and_queue/queue.md b/docs/chapter_stack_and_queue/queue.md index 5dc437791..f0ce67d10 100755 --- a/docs/chapter_stack_and_queue/queue.md +++ b/docs/chapter_stack_and_queue/queue.md @@ -684,9 +684,11 @@ comments: true class LinkedListQueue { private var front: ListNode? // 头节点 private var rear: ListNode? // 尾节点 - private var _size = 0 + private var _size: Int - init() {} + init() { + _size = 0 + } /* 获取队列的长度 */ func size() -> Int { @@ -1605,12 +1607,14 @@ comments: true /* 基于环形数组实现的队列 */ class ArrayQueue { private var nums: [Int] // 用于存储队列元素的数组 - private var front = 0 // 队首指针,指向队首元素 - private var queSize = 0 // 队列长度 + private var front: Int // 队首指针,指向队首元素 + private var _size: Int // 队列长度 init(capacity: Int) { // 初始化数组 nums = Array(repeating: 0, count: capacity) + front = 0 + _size = 0 } /* 获取队列的容量 */ @@ -1620,12 +1624,12 @@ comments: true /* 获取队列的长度 */ func size() -> Int { - queSize + _size } /* 判断队列是否为空 */ func isEmpty() -> Bool { - queSize == 0 + size() == 0 } /* 入队 */ @@ -1636,10 +1640,10 @@ comments: true } // 计算队尾指针,指向队尾索引 + 1 // 通过取余操作实现 rear 越过数组尾部后回到头部 - let rear = (front + queSize) % capacity() + let rear = (front + size()) % capacity() // 将 num 添加至队尾 nums[rear] = num - queSize += 1 + _size += 1 } /* 出队 */ @@ -1648,7 +1652,7 @@ comments: true let num = peek() // 队首指针向后移动一位,若越过尾部,则返回到数组头部 front = (front + 1) % capacity() - queSize -= 1 + _size -= 1 return num } @@ -1663,11 +1667,7 @@ comments: true /* 返回数组 */ func toArray() -> [Int] { // 仅转换有效长度范围内的列表元素 - var res = Array(repeating: 0, count: queSize) - for (i, j) in sequence(first: (0, front), next: { $0 < self.queSize - 1 ? ($0 + 1, $1 + 1) : nil }) { - res[i] = nums[j % capacity()] - } - return res + (front ..< front + size()).map { nums[$0 % capacity()] } } } ``` diff --git a/docs/chapter_stack_and_queue/stack.md b/docs/chapter_stack_and_queue/stack.md index fe10f9864..1537c95cd 100755 --- a/docs/chapter_stack_and_queue/stack.md +++ b/docs/chapter_stack_and_queue/stack.md @@ -643,9 +643,11 @@ comments: true /* 基于链表实现的栈 */ class LinkedListStack { private var _peek: ListNode? // 将头节点作为栈顶 - private var _size = 0 // 栈的长度 + private var _size: Int // 栈的长度 - init() {} + init() { + _size = 0 + } /* 获取栈的长度 */ func size() -> Int { @@ -685,8 +687,8 @@ comments: true /* 将 List 转化为 Array 并返回 */ func toArray() -> [Int] { var node = _peek - var res = Array(repeating: 0, count: _size) - for i in sequence(first: res.count - 1, next: { $0 >= 0 + 1 ? $0 - 1 : nil }) { + var res = Array(repeating: 0, count: size()) + for i in res.indices.reversed() { res[i] = node!.val node = node?.next } diff --git a/docs/chapter_tree/array_representation_of_tree.md b/docs/chapter_tree/array_representation_of_tree.md index fb38f4cf9..4515667c1 100644 --- a/docs/chapter_tree/array_representation_of_tree.md +++ b/docs/chapter_tree/array_representation_of_tree.md @@ -638,7 +638,7 @@ comments: true func levelOrder() -> [Int] { var res: [Int] = [] // 直接遍历数组 - for i in stride(from: 0, to: size(), by: 1) { + for i in 0 ..< size() { if let val = val(i: i) { res.append(val) } diff --git a/docs/chapter_tree/avl_tree.md b/docs/chapter_tree/avl_tree.md index 8bdbf0640..2e95f1649 100644 --- a/docs/chapter_tree/avl_tree.md +++ b/docs/chapter_tree/avl_tree.md @@ -311,7 +311,7 @@ AVL 树既是二叉搜索树,也是平衡二叉树,同时满足这两类二 /* 获取节点高度 */ func height(node: TreeNode?) -> Int { // 空节点高度为 -1 ,叶节点高度为 0 - node == nil ? -1 : node!.height + node?.height ?? -1 } /* 更新节点高度 */ @@ -2142,7 +2142,7 @@ AVL 树的节点插入操作与二叉搜索树在主体上类似。唯一的区 node?.right = removeHelper(node: node?.right, val: val) } else { if node?.left == nil || node?.right == nil { - let child = node?.left != nil ? node?.left : node?.right + let child = node?.left ?? node?.right // 子节点数量 = 0 ,直接删除 node 并返回 if child == nil { return nil diff --git a/docs/chapter_tree/binary_search_tree.md b/docs/chapter_tree/binary_search_tree.md index fa8aef29f..280235bd1 100755 --- a/docs/chapter_tree/binary_search_tree.md +++ b/docs/chapter_tree/binary_search_tree.md @@ -1106,7 +1106,7 @@ comments: true // 子节点数量 = 0 or 1 if cur?.left == nil || cur?.right == nil { // 当子节点数量 = 0 / 1 时, child = null / 该子节点 - let child = cur?.left != nil ? cur?.left : cur?.right + let child = cur?.left ?? cur?.right // 删除节点 cur if cur !== root { if pre?.left === cur {