krahets 8 months ago
parent 35a07170c0
commit cfdb743939

@ -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
}
}
```

@ -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
}
```

@ -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()))
}
}
```

@ -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)
}

@ -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] {

@ -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"

@ -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 对应的桶索引 */

@ -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 }
}
/* 打印哈希表 */

@ -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
}
/* 返回数组用于打印 */

@ -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()] }
}
}
```

@ -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
}

@ -6,8 +6,8 @@ comments: true
表 16-1 列出了书中出现的重要术语,值得注意以下几点。
- 部分名词在简体中文和繁体中文下的叫法不同。
- 建议记住名词的英文叫法,以便阅读英文文献。
- 部分名词在简体中文和繁体中文下的叫法不同。
<p align="center"> 表 16-1 &nbsp; 数据结构与算法的重要名词 </p>
@ -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
| 2s 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 | 贪心算法 | 貪演算法 |
</div>

@ -750,6 +750,11 @@ comments: true
for num in nums {
count += num
}
// 同时遍历数据索引和元素
for (i, num) in nums.enumerated() {
count += nums[i]
count += num
}
}
```

@ -644,7 +644,6 @@ comments: true
let P = n0.next
let n1 = P?.next
n0.next = n1
P?.next = nil
}
```

@ -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()))
}
}
```

@ -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 {

@ -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)
}

@ -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] {

@ -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"

@ -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)
}
```

@ -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)
}
```

@ -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]
}

@ -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]
}
}

@ -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] {
// 若两字符相等,则直接跳过此两字符

@ -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

@ -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])

@ -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]

@ -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),")
}
}
}

@ -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

@ -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
// 循环贪心选择,直至两板相遇

@ -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 对应的桶索引 */

@ -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 }
}
/* 打印哈希表 */

@ -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)
}
}

@ -280,7 +280,35 @@ comments: true
=== "Swift"
```swift title="heap.swift"
// Swift 未提供内置 Heap 类
/* 初始化堆 */
// Swift 的 Heap 类型同时支持最大堆和最小堆,且需要引入 swift-collections
var heap = Heap<Int>()
/* 元素入堆 */
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"

@ -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()

@ -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

@ -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

@ -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 {

@ -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 // 记录交换元素
}
}

@ -203,7 +203,7 @@ comments: true
for bucket in buckets {
for num in bucket {
nums[i] = num
nums.formIndex(after: &i)
i += 1
}
}
}

@ -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]
}
}

@ -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)
// 以根节点为起点,从顶至底进行堆化

@ -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] 中的正确位置

@ -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 {

@ -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)
}
```

@ -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

@ -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)] }
}
}
```

@ -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()] }
}
}
```

@ -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
}

@ -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)
}

@ -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

@ -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 {

Loading…
Cancel
Save