diff --git a/.github/workflows/swift.yml b/.github/workflows/swift.yml index b9c88b5f0..1a8218bb7 100644 --- a/.github/workflows/swift.yml +++ b/.github/workflows/swift.yml @@ -19,9 +19,9 @@ jobs: strategy: matrix: os: [ubuntu-latest, macos-latest] - swift: ["5.9", "5.8.1", "5.7.3"] + swift: ["5.10", "5.9", "5.8"] steps: - - uses: swift-actions/setup-swift@v1 + - uses: swift-actions/setup-swift@v2 with: swift-version: ${{ matrix.swift }} - uses: actions/checkout@v4 diff --git a/codes/swift/Package.swift b/codes/swift/Package.swift index 7f67d18a2..5326dc138 100644 --- a/codes/swift/Package.swift +++ b/codes/swift/Package.swift @@ -41,6 +41,7 @@ let package = Package( .executable(name: "binary_search_tree", targets: ["binary_search_tree"]), .executable(name: "avl_tree", targets: ["avl_tree"]), // chapter_heap + .executable(name: "heap", targets: ["heap"]), .executable(name: "my_heap", targets: ["my_heap"]), .executable(name: "top_k", targets: ["top_k"]), // chapter_graph @@ -143,6 +144,7 @@ let package = Package( .executableTarget(name: "binary_search_tree", dependencies: ["utils"], path: "chapter_tree", sources: ["binary_search_tree.swift"]), .executableTarget(name: "avl_tree", dependencies: ["utils"], path: "chapter_tree", sources: ["avl_tree.swift"]), // chapter_heap + .executableTarget(name: "heap", dependencies: ["utils", .product(name: "HeapModule", package: "swift-collections")], path: "chapter_heap", sources: ["heap.swift"]), .executableTarget(name: "my_heap", dependencies: ["utils"], path: "chapter_heap", sources: ["my_heap.swift"]), .executableTarget(name: "top_k", dependencies: ["utils", .product(name: "HeapModule", package: "swift-collections")], path: "chapter_heap", sources: ["top_k.swift"]), // chapter_graph diff --git a/codes/swift/chapter_array_and_linkedlist/array.swift b/codes/swift/chapter_array_and_linkedlist/array.swift index bc96d1d8a..5b0024931 100644 --- a/codes/swift/chapter_array_and_linkedlist/array.swift +++ b/codes/swift/chapter_array_and_linkedlist/array.swift @@ -54,6 +54,11 @@ func traverse(nums: [Int]) { for num in nums { count += num } + // 同时遍历数据索引和元素 + for (i, num) in nums.enumerated() { + count += nums[i] + count += num + } } /* 在数组中查找指定元素 */ diff --git a/codes/swift/chapter_array_and_linkedlist/linked_list.swift b/codes/swift/chapter_array_and_linkedlist/linked_list.swift index dae3aa55c..907db057d 100644 --- a/codes/swift/chapter_array_and_linkedlist/linked_list.swift +++ b/codes/swift/chapter_array_and_linkedlist/linked_list.swift @@ -22,7 +22,6 @@ func remove(n0: ListNode) { let P = n0.next let n1 = P?.next n0.next = n1 - P?.next = nil } /* 访问链表中索引为 index 的节点 */ diff --git a/codes/swift/chapter_array_and_linkedlist/my_list.swift b/codes/swift/chapter_array_and_linkedlist/my_list.swift index 4fd725f34..f170dc3d4 100644 --- a/codes/swift/chapter_array_and_linkedlist/my_list.swift +++ b/codes/swift/chapter_array_and_linkedlist/my_list.swift @@ -7,12 +7,15 @@ /* 列表类 */ 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) } @@ -29,7 +32,7 @@ class MyList { /* 访问元素 */ func get(index: Int) -> Int { // 索引如果越界则抛出错误,下同 - if index < 0 || index >= _size { + if index < 0 || index >= size() { fatalError("索引越界") } return arr[index] @@ -37,7 +40,7 @@ class MyList { /* 更新元素 */ func set(index: Int, num: Int) { - if index < 0 || index >= _size { + if index < 0 || index >= size() { fatalError("索引越界") } arr[index] = num @@ -46,25 +49,25 @@ class MyList { /* 在尾部添加元素 */ 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 @@ -75,12 +78,12 @@ class MyList { /* 删除元素 */ @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] } // 更新元素数量 @@ -92,18 +95,14 @@ class MyList { /* 列表扩容 */ 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/codes/swift/chapter_backtracking/subset_sum_i.swift b/codes/swift/chapter_backtracking/subset_sum_i.swift index 470d06cf9..b19fd112c 100644 --- a/codes/swift/chapter_backtracking/subset_sum_i.swift +++ b/codes/swift/chapter_backtracking/subset_sum_i.swift @@ -13,7 +13,7 @@ func backtrack(state: inout [Int], target: Int, choices: [Int], start: Int, res: } // 遍历所有选择 // 剪枝二:从 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/codes/swift/chapter_backtracking/subset_sum_i_naive.swift b/codes/swift/chapter_backtracking/subset_sum_i_naive.swift index b40b793c5..57e6a6d89 100644 --- a/codes/swift/chapter_backtracking/subset_sum_i_naive.swift +++ b/codes/swift/chapter_backtracking/subset_sum_i_naive.swift @@ -12,7 +12,7 @@ func backtrack(state: inout [Int], target: Int, total: Int, choices: [Int], res: return } // 遍历所有选择 - for i in stride(from: 0, to: choices.count, by: 1) { + for i in choices.indices { // 剪枝:若子集和超过 target ,则跳过该选择 if total + choices[i] > target { continue diff --git a/codes/swift/chapter_backtracking/subset_sum_ii.swift b/codes/swift/chapter_backtracking/subset_sum_ii.swift index f3e494cf1..91cc39dda 100644 --- a/codes/swift/chapter_backtracking/subset_sum_ii.swift +++ b/codes/swift/chapter_backtracking/subset_sum_ii.swift @@ -14,7 +14,7 @@ func backtrack(state: inout [Int], target: Int, choices: [Int], start: Int, res: // 遍历所有选择 // 剪枝二:从 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/codes/swift/chapter_computational_complexity/recursion.swift b/codes/swift/chapter_computational_complexity/recursion.swift index 9d3fedc96..87c755356 100644 --- a/codes/swift/chapter_computational_complexity/recursion.swift +++ b/codes/swift/chapter_computational_complexity/recursion.swift @@ -22,7 +22,7 @@ func forLoopRecur(n: Int) -> Int { 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/codes/swift/chapter_computational_complexity/time_complexity.swift b/codes/swift/chapter_computational_complexity/time_complexity.swift index 3581752be..e50e9fa3d 100644 --- a/codes/swift/chapter_computational_complexity/time_complexity.swift +++ b/codes/swift/chapter_computational_complexity/time_complexity.swift @@ -49,7 +49,7 @@ func quadratic(n: Int) -> Int { 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/codes/swift/chapter_divide_and_conquer/binary_search_recur.swift b/codes/swift/chapter_divide_and_conquer/binary_search_recur.swift index 1128d378a..9aa25b133 100644 --- a/codes/swift/chapter_divide_and_conquer/binary_search_recur.swift +++ b/codes/swift/chapter_divide_and_conquer/binary_search_recur.swift @@ -26,9 +26,8 @@ func dfs(nums: [Int], target: Int, i: Int, j: Int) -> Int { /* 二分查找 */ 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) } @main diff --git a/codes/swift/chapter_divide_and_conquer/build_tree.swift b/codes/swift/chapter_divide_and_conquer/build_tree.swift index bd94ba467..86193ddea 100644 --- a/codes/swift/chapter_divide_and_conquer/build_tree.swift +++ b/codes/swift/chapter_divide_and_conquer/build_tree.swift @@ -28,7 +28,7 @@ func dfs(preorder: [Int], inorderMap: [Int: Int], i: Int, l: Int, r: Int) -> Tre 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) } @main diff --git a/codes/swift/chapter_dynamic_programming/climbing_stairs_constraint_dp.swift b/codes/swift/chapter_dynamic_programming/climbing_stairs_constraint_dp.swift index a40425211..176b2717d 100644 --- a/codes/swift/chapter_dynamic_programming/climbing_stairs_constraint_dp.swift +++ b/codes/swift/chapter_dynamic_programming/climbing_stairs_constraint_dp.swift @@ -17,7 +17,7 @@ func climbingStairsConstraintDP(n: Int) -> Int { 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/codes/swift/chapter_dynamic_programming/climbing_stairs_dp.swift b/codes/swift/chapter_dynamic_programming/climbing_stairs_dp.swift index d36741c65..4814ec5ee 100644 --- a/codes/swift/chapter_dynamic_programming/climbing_stairs_dp.swift +++ b/codes/swift/chapter_dynamic_programming/climbing_stairs_dp.swift @@ -15,7 +15,7 @@ func climbingStairsDP(n: Int) -> Int { 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] @@ -28,7 +28,7 @@ func climbingStairsDPComp(n: Int) -> Int { } 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/codes/swift/chapter_dynamic_programming/coin_change.swift b/codes/swift/chapter_dynamic_programming/coin_change.swift index 08906ec67..6558b6aa4 100644 --- a/codes/swift/chapter_dynamic_programming/coin_change.swift +++ b/codes/swift/chapter_dynamic_programming/coin_change.swift @@ -11,12 +11,12 @@ func coinChangeDP(coins: [Int], amt: Int) -> Int { // 初始化 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] @@ -37,8 +37,8 @@ func coinChangeDPComp(coins: [Int], amt: Int) -> Int { 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] diff --git a/codes/swift/chapter_dynamic_programming/coin_change_ii.swift b/codes/swift/chapter_dynamic_programming/coin_change_ii.swift index 5b4e8abd5..b1229f728 100644 --- a/codes/swift/chapter_dynamic_programming/coin_change_ii.swift +++ b/codes/swift/chapter_dynamic_programming/coin_change_ii.swift @@ -10,12 +10,12 @@ func coinChangeIIDP(coins: [Int], amt: Int) -> Int { // 初始化 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] @@ -35,8 +35,8 @@ func coinChangeIIDPComp(coins: [Int], amt: Int) -> Int { 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/codes/swift/chapter_dynamic_programming/edit_distance.swift b/codes/swift/chapter_dynamic_programming/edit_distance.swift index 51ea34a4d..a10852332 100644 --- a/codes/swift/chapter_dynamic_programming/edit_distance.swift +++ b/codes/swift/chapter_dynamic_programming/edit_distance.swift @@ -67,15 +67,15 @@ func editDistanceDP(s: String, t: String) -> Int { 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] @@ -94,16 +94,16 @@ func editDistanceDPComp(s: String, t: String) -> Int { 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/codes/swift/chapter_dynamic_programming/knapsack.swift b/codes/swift/chapter_dynamic_programming/knapsack.swift index cc9378cce..ec677a3c2 100644 --- a/codes/swift/chapter_dynamic_programming/knapsack.swift +++ b/codes/swift/chapter_dynamic_programming/knapsack.swift @@ -49,8 +49,8 @@ func knapsackDP(wgt: [Int], val: [Int], cap: Int) -> Int { // 初始化 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] @@ -69,9 +69,9 @@ func knapsackDPComp(wgt: [Int], val: [Int], cap: Int) -> Int { // 初始化 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/codes/swift/chapter_dynamic_programming/min_cost_climbing_stairs_dp.swift b/codes/swift/chapter_dynamic_programming/min_cost_climbing_stairs_dp.swift index a86a86bb5..5f7cb9a26 100644 --- a/codes/swift/chapter_dynamic_programming/min_cost_climbing_stairs_dp.swift +++ b/codes/swift/chapter_dynamic_programming/min_cost_climbing_stairs_dp.swift @@ -16,7 +16,7 @@ func minCostClimbingStairsDP(cost: [Int]) -> Int { 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] @@ -29,7 +29,7 @@ func minCostClimbingStairsDPComp(cost: [Int]) -> Int { 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 diff --git a/codes/swift/chapter_dynamic_programming/min_path_sum.swift b/codes/swift/chapter_dynamic_programming/min_path_sum.swift index 014d08b5b..640633acf 100644 --- a/codes/swift/chapter_dynamic_programming/min_path_sum.swift +++ b/codes/swift/chapter_dynamic_programming/min_path_sum.swift @@ -51,16 +51,16 @@ func minPathSumDP(grid: [[Int]]) -> Int { 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] } } @@ -75,15 +75,15 @@ func minPathSumDPComp(grid: [[Int]]) -> Int { 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/codes/swift/chapter_dynamic_programming/unbounded_knapsack.swift b/codes/swift/chapter_dynamic_programming/unbounded_knapsack.swift index a0699b301..39bc3df1c 100644 --- a/codes/swift/chapter_dynamic_programming/unbounded_knapsack.swift +++ b/codes/swift/chapter_dynamic_programming/unbounded_knapsack.swift @@ -10,8 +10,8 @@ func unboundedKnapsackDP(wgt: [Int], val: [Int], cap: Int) -> Int { // 初始化 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] @@ -30,8 +30,8 @@ func unboundedKnapsackDPComp(wgt: [Int], val: [Int], cap: Int) -> Int { // 初始化 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] diff --git a/codes/swift/chapter_graph/graph_adjacency_list.swift b/codes/swift/chapter_graph/graph_adjacency_list.swift index ff88186c3..e388c605c 100644 --- a/codes/swift/chapter_graph/graph_adjacency_list.swift +++ b/codes/swift/chapter_graph/graph_adjacency_list.swift @@ -43,8 +43,8 @@ public class GraphAdjList { 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 } } /* 添加顶点 */ @@ -65,19 +65,16 @@ public class GraphAdjList { 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/codes/swift/chapter_greedy/fractional_knapsack.swift b/codes/swift/chapter_greedy/fractional_knapsack.swift index e25b022df..650eb95a3 100644 --- a/codes/swift/chapter_greedy/fractional_knapsack.swift +++ b/codes/swift/chapter_greedy/fractional_knapsack.swift @@ -20,7 +20,7 @@ func fractionalKnapsack(wgt: [Int], val: [Int], cap: Int) -> Double { // 创建物品列表,包含两个属性:重量、价值 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/codes/swift/chapter_greedy/max_capacity.swift b/codes/swift/chapter_greedy/max_capacity.swift index feedd38fc..dde37ca97 100644 --- a/codes/swift/chapter_greedy/max_capacity.swift +++ b/codes/swift/chapter_greedy/max_capacity.swift @@ -7,7 +7,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/codes/swift/chapter_hashing/array_hash_map.swift b/codes/swift/chapter_hashing/array_hash_map.swift index 882eb96bd..f65cdf9e1 100644 --- a/codes/swift/chapter_hashing/array_hash_map.swift +++ b/codes/swift/chapter_hashing/array_hash_map.swift @@ -8,13 +8,11 @@ import utils /* 基于数组实现的哈希表 */ 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) } /* 哈希函数 */ @@ -46,35 +44,17 @@ class ArrayHashMap { /* 获取所有键值对 */ 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/codes/swift/chapter_hashing/hash_map_chaining.swift b/codes/swift/chapter_hashing/hash_map_chaining.swift index 745fca461..878ce4164 100644 --- a/codes/swift/chapter_hashing/hash_map_chaining.swift +++ b/codes/swift/chapter_hashing/hash_map_chaining.swift @@ -30,7 +30,7 @@ class HashMapChaining { /* 负载因子 */ func loadFactor() -> Double { - Double(size / capacity) + Double(size) / Double(capacity) } /* 查询操作 */ @@ -76,9 +76,10 @@ class HashMapChaining { for (pairIndex, pair) in bucket.enumerated() { if pair.key == key { buckets[index].remove(at: pairIndex) + size -= 1 + break } } - size -= 1 } /* 扩容哈希表 */ diff --git a/codes/swift/chapter_hashing/hash_map_open_addressing.swift b/codes/swift/chapter_hashing/hash_map_open_addressing.swift index d7515d57a..e65bca370 100644 --- a/codes/swift/chapter_hashing/hash_map_open_addressing.swift +++ b/codes/swift/chapter_hashing/hash_map_open_addressing.swift @@ -32,7 +32,7 @@ class HashMapOpenAddressing { /* 负载因子 */ func loadFactor() -> Double { - Double(size / capacity) + Double(size) / Double(capacity) } /* 搜索 key 对应的桶索引 */ diff --git a/codes/swift/chapter_heap/heap.swift b/codes/swift/chapter_heap/heap.swift new file mode 100644 index 000000000..fc85880a0 --- /dev/null +++ b/codes/swift/chapter_heap/heap.swift @@ -0,0 +1,62 @@ +/** + * File: heap.swift + * Created Time: 2024-03-17 + * Author: nuomi1 (nuomi1@qq.com) + */ + +import HeapModule +import utils + +func testPush(heap: inout Heap, val: Int) { + heap.insert(val) + print("\n元素 \(val) 入堆后\n") + PrintUtil.printHeap(queue: heap.unordered) +} + +func testPop(heap: inout Heap) { + let val = heap.removeMax() + print("\n堆顶元素 \(val) 出堆后\n") + PrintUtil.printHeap(queue: heap.unordered) +} + +@main +enum _Heap { + /* Driver Code */ + static func main() { + /* 初始化堆 */ + // Swift 的 Heap 类型同时支持最大堆和最小堆 + var heap = Heap() + + /* 元素入堆 */ + testPush(heap: &heap, val: 1) + testPush(heap: &heap, val: 3) + testPush(heap: &heap, val: 2) + testPush(heap: &heap, val: 5) + testPush(heap: &heap, val: 4) + + /* 获取堆顶元素 */ + let peek = heap.max() + print("\n堆顶元素为 \(peek!)\n") + + /* 堆顶元素出堆 */ + testPop(heap: &heap) + testPop(heap: &heap) + testPop(heap: &heap) + testPop(heap: &heap) + testPop(heap: &heap) + + /* 获取堆大小 */ + let size = heap.count + print("\n堆元素数量为 \(size)\n") + + /* 判断堆是否为空 */ + let isEmpty = heap.isEmpty + print("\n堆是否为空 \(isEmpty)\n") + + /* 输入列表并建堆 */ + // 时间复杂度为 O(n) ,而非 O(nlogn) + let heap2 = Heap([1, 3, 2, 5, 4]) + print("\n输入列表并建立堆后") + PrintUtil.printHeap(queue: heap2.unordered) + } +} diff --git a/codes/swift/chapter_heap/my_heap.swift b/codes/swift/chapter_heap/my_heap.swift index 96152f520..cc388d47b 100644 --- a/codes/swift/chapter_heap/my_heap.swift +++ b/codes/swift/chapter_heap/my_heap.swift @@ -15,7 +15,7 @@ class MaxHeap { // 将列表元素原封不动添加进堆 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/codes/swift/chapter_heap/top_k.swift b/codes/swift/chapter_heap/top_k.swift index 6c0cb91df..bd13e7169 100644 --- a/codes/swift/chapter_heap/top_k.swift +++ b/codes/swift/chapter_heap/top_k.swift @@ -12,7 +12,7 @@ func topKHeap(nums: [Int], k: Int) -> [Int] { // 初始化一个小顶堆,并将前 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/codes/swift/chapter_searching/binary_search.swift b/codes/swift/chapter_searching/binary_search.swift index 28b8b7af2..21d5e7fc2 100644 --- a/codes/swift/chapter_searching/binary_search.swift +++ b/codes/swift/chapter_searching/binary_search.swift @@ -7,8 +7,8 @@ /* 二分查找(双闭区间) */ 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 @@ -27,8 +27,8 @@ func binarySearch(nums: [Int], target: Int) -> Int { /* 二分查找(左闭右开区间) */ 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/codes/swift/chapter_searching/binary_search_edge.swift b/codes/swift/chapter_searching/binary_search_edge.swift index 439760899..0bc50dfed 100644 --- a/codes/swift/chapter_searching/binary_search_edge.swift +++ b/codes/swift/chapter_searching/binary_search_edge.swift @@ -11,7 +11,7 @@ func binarySearchLeftEdge(nums: [Int], target: Int) -> Int { // 等价于查找 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/codes/swift/chapter_searching/binary_search_insertion.swift b/codes/swift/chapter_searching/binary_search_insertion.swift index 44d2e85cf..ced9f1d87 100644 --- a/codes/swift/chapter_searching/binary_search_insertion.swift +++ b/codes/swift/chapter_searching/binary_search_insertion.swift @@ -6,7 +6,9 @@ /* 二分查找插入点(无重复元素) */ 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 { @@ -23,7 +25,9 @@ func binarySearchInsertionSimple(nums: [Int], target: Int) -> Int { /* 二分查找插入点(存在重复元素) */ public 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/codes/swift/chapter_sorting/bubble_sort.swift b/codes/swift/chapter_sorting/bubble_sort.swift index 15ff9d7e8..8069cf67b 100644 --- a/codes/swift/chapter_sorting/bubble_sort.swift +++ b/codes/swift/chapter_sorting/bubble_sort.swift @@ -7,14 +7,12 @@ /* 冒泡排序 */ 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) } } } @@ -23,14 +21,12 @@ func bubbleSort(nums: inout [Int]) { /* 冒泡排序(标志优化)*/ 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/codes/swift/chapter_sorting/bucket_sort.swift b/codes/swift/chapter_sorting/bucket_sort.swift index 037136b71..2be527fb7 100644 --- a/codes/swift/chapter_sorting/bucket_sort.swift +++ b/codes/swift/chapter_sorting/bucket_sort.swift @@ -26,7 +26,7 @@ func bucketSort(nums: inout [Double]) { for bucket in buckets { for num in bucket { nums[i] = num - nums.formIndex(after: &i) + i += 1 } } } diff --git a/codes/swift/chapter_sorting/counting_sort.swift b/codes/swift/chapter_sorting/counting_sort.swift index b2194323d..f702848a2 100644 --- a/codes/swift/chapter_sorting/counting_sort.swift +++ b/codes/swift/chapter_sorting/counting_sort.swift @@ -17,8 +17,8 @@ func countingSortNaive(nums: inout [Int]) { } // 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 } @@ -38,19 +38,19 @@ func countingSort(nums: inout [Int]) { } // 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/codes/swift/chapter_sorting/heap_sort.swift b/codes/swift/chapter_sorting/heap_sort.swift index 4e5ec1e6d..ca1d72665 100644 --- a/codes/swift/chapter_sorting/heap_sort.swift +++ b/codes/swift/chapter_sorting/heap_sort.swift @@ -36,7 +36,7 @@ func heapSort(nums: inout [Int]) { 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/codes/swift/chapter_sorting/insertion_sort.swift b/codes/swift/chapter_sorting/insertion_sort.swift index e86f1dba0..4bc8441e0 100644 --- a/codes/swift/chapter_sorting/insertion_sort.swift +++ b/codes/swift/chapter_sorting/insertion_sort.swift @@ -7,7 +7,7 @@ /* 插入排序 */ 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/codes/swift/chapter_sorting/merge_sort.swift b/codes/swift/chapter_sorting/merge_sort.swift index 1cf8b63da..e587c1578 100644 --- a/codes/swift/chapter_sorting/merge_sort.swift +++ b/codes/swift/chapter_sorting/merge_sort.swift @@ -16,12 +16,11 @@ func merge(nums: inout [Int], left: Int, mid: Int, right: Int) { 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 { @@ -60,7 +59,7 @@ enum MergeSort { static func main() { /* 归并排序 */ var nums = [7, 3, 2, 6, 0, 1, 5, 4] - mergeSort(nums: &nums, left: 0, right: nums.count - 1) + mergeSort(nums: &nums, left: nums.startIndex, right: nums.endIndex - 1) print("归并排序完成后 nums = \(nums)") } } diff --git a/codes/swift/chapter_sorting/quick_sort.swift b/codes/swift/chapter_sorting/quick_sort.swift index 21a72534b..957e86471 100644 --- a/codes/swift/chapter_sorting/quick_sort.swift +++ b/codes/swift/chapter_sorting/quick_sort.swift @@ -4,13 +4,6 @@ * Author: nuomi1 (nuomi1@qq.com) */ -/* 元素交换 */ -func swap(nums: inout [Int], i: Int, j: Int) { - let tmp = nums[i] - nums[i] = nums[j] - nums[j] = tmp -} - /* 快速排序类 */ /* 哨兵划分 */ func partition(nums: inout [Int], left: Int, right: Int) -> Int { @@ -24,9 +17,9 @@ func partition(nums: inout [Int], left: Int, right: Int) -> Int { 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 // 返回基准数的索引 } @@ -43,7 +36,6 @@ func quickSort(nums: inout [Int], left: Int, right: Int) { quickSort(nums: &nums, left: pivot + 1, right: right) } - /* 快速排序类(中位基准数优化) */ /* 选取三个候选元素的中位数 */ func medianThree(nums: [Int], left: Int, mid: Int, right: Int) -> Int { @@ -51,12 +43,12 @@ func medianThree(nums: [Int], left: Int, mid: Int, right: Int) -> Int { 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 } /* 哨兵划分(三数取中值) */ @@ -64,7 +56,7 @@ func partitionMedian(nums: inout [Int], left: Int, right: Int) -> Int { // 选取三个候选元素的中位数 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) } @@ -81,7 +73,6 @@ func quickSortMedian(nums: inout [Int], left: Int, right: Int) { quickSortMedian(nums: &nums, left: pivot + 1, right: right) } - /* 快速排序(尾递归优化) */ func quickSortTailCall(nums: inout [Int], left: Int, right: Int) { var left = left @@ -107,17 +98,17 @@ enum QuickSort { static func main() { /* 快速排序 */ var nums = [2, 4, 1, 0, 3, 5] - quickSort(nums: &nums, left: 0, right: nums.count - 1) + quickSort(nums: &nums, left: nums.startIndex, right: nums.endIndex - 1) print("快速排序完成后 nums = \(nums)") /* 快速排序(中位基准数优化) */ var nums1 = [2, 4, 1, 0, 3, 5] - quickSortMedian(nums: &nums1, left: 0, right: nums1.count - 1) + quickSortMedian(nums: &nums1, left: nums1.startIndex, right: nums1.endIndex - 1) print("快速排序(中位基准数优化)完成后 nums1 = \(nums1)") /* 快速排序(尾递归优化) */ var nums2 = [2, 4, 1, 0, 3, 5] - quickSortTailCall(nums: &nums2, left: 0, right: nums2.count - 1) + quickSortTailCall(nums: &nums2, left: nums2.startIndex, right: nums2.endIndex - 1) print("快速排序(尾递归优化)完成后 nums2 = \(nums2)") } } diff --git a/codes/swift/chapter_sorting/radix_sort.swift b/codes/swift/chapter_sorting/radix_sort.swift index 8152e4d59..2ef0fd8f8 100644 --- a/codes/swift/chapter_sorting/radix_sort.swift +++ b/codes/swift/chapter_sorting/radix_sort.swift @@ -14,7 +14,6 @@ func digit(num: Int, exp: Int) -> Int { 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 @@ -25,8 +24,8 @@ func countingSortDigit(nums: inout [Int], exp: Int) { 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 @@ -62,8 +61,18 @@ enum RadixSort { /* Driver Code */ static func main() { // 基数排序 - var nums = [10546151, 35663510, 42865989, 34862445, 81883077, - 88906420, 72429244, 30524779, 82060337, 63832996] + var nums = [ + 10_546_151, + 35_663_510, + 42_865_989, + 34_862_445, + 81_883_077, + 88_906_420, + 72_429_244, + 30_524_779, + 82_060_337, + 63_832_996, + ] radixSort(nums: &nums) print("基数排序完成后 nums = \(nums)") } diff --git a/codes/swift/chapter_stack_and_queue/array_deque.swift b/codes/swift/chapter_stack_and_queue/array_deque.swift index 7051572cb..549395bfe 100644 --- a/codes/swift/chapter_stack_and_queue/array_deque.swift +++ b/codes/swift/chapter_stack_and_queue/array_deque.swift @@ -8,13 +8,13 @@ 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 } /* 获取双向队列的容量 */ @@ -24,7 +24,7 @@ class ArrayDeque { /* 获取双向队列的长度 */ func size() -> Int { - queSize + _size } /* 判断双向队列是否为空 */ @@ -51,7 +51,7 @@ class ArrayDeque { front = index(i: front - 1) // 将 num 添加至队首 nums[front] = num - queSize += 1 + _size += 1 } /* 队尾入队 */ @@ -64,7 +64,7 @@ class ArrayDeque { let rear = index(i: front + size()) // 将 num 添加至队尾 nums[rear] = num - queSize += 1 + _size += 1 } /* 队首出队 */ @@ -72,14 +72,14 @@ class ArrayDeque { 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 } @@ -104,11 +104,7 @@ class ArrayDeque { /* 返回数组用于打印 */ 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/codes/swift/chapter_stack_and_queue/array_queue.swift b/codes/swift/chapter_stack_and_queue/array_queue.swift index 2a6449956..8bfe82e16 100644 --- a/codes/swift/chapter_stack_and_queue/array_queue.swift +++ b/codes/swift/chapter_stack_and_queue/array_queue.swift @@ -7,12 +7,14 @@ /* 基于环形数组实现的队列 */ 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 } /* 获取队列的容量 */ @@ -22,12 +24,12 @@ class ArrayQueue { /* 获取队列的长度 */ func size() -> Int { - queSize + _size } /* 判断队列是否为空 */ func isEmpty() -> Bool { - queSize == 0 + size() == 0 } /* 入队 */ @@ -38,10 +40,10 @@ class ArrayQueue { } // 计算队尾指针,指向队尾索引 + 1 // 通过取余操作实现 rear 越过数组尾部后回到头部 - let rear = (front + queSize) % capacity() + let rear = (front + size()) % capacity() // 将 num 添加至队尾 nums[rear] = num - queSize += 1 + _size += 1 } /* 出队 */ @@ -50,7 +52,7 @@ class ArrayQueue { let num = peek() // 队首指针向后移动一位,若越过尾部,则返回到数组头部 front = (front + 1) % capacity() - queSize -= 1 + _size -= 1 return num } @@ -65,11 +67,7 @@ class ArrayQueue { /* 返回数组 */ 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/codes/swift/chapter_stack_and_queue/linkedlist_deque.swift b/codes/swift/chapter_stack_and_queue/linkedlist_deque.swift index edd9cd2f7..d5318294e 100644 --- a/codes/swift/chapter_stack_and_queue/linkedlist_deque.swift +++ b/codes/swift/chapter_stack_and_queue/linkedlist_deque.swift @@ -19,15 +19,15 @@ class ListNode { 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 } /* 判断双向队列是否为空 */ @@ -57,7 +57,7 @@ class LinkedListDeque { node.prev = rear rear = node // 更新尾节点 } - queSize += 1 // 更新队列长度 + _size += 1 // 更新队列长度 } /* 队首入队 */ @@ -98,7 +98,7 @@ class LinkedListDeque { } rear = rPrev // 更新尾节点 } - queSize -= 1 // 更新队列长度 + _size -= 1 // 更新队列长度 return val } @@ -113,13 +113,19 @@ class LinkedListDeque { } /* 访问队首元素 */ - 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 } /* 返回数组用于打印 */ @@ -147,9 +153,9 @@ enum _LinkedListDeque { /* 访问元素 */ let peekFirst = deque.peekFirst() - print("队首元素 peekFirst = \(peekFirst!)") + print("队首元素 peekFirst = \(peekFirst)") let peekLast = deque.peekLast() - print("队尾元素 peekLast = \(peekLast!)") + print("队尾元素 peekLast = \(peekLast)") /* 元素入队 */ deque.pushLast(num: 4) diff --git a/codes/swift/chapter_stack_and_queue/linkedlist_queue.swift b/codes/swift/chapter_stack_and_queue/linkedlist_queue.swift index 623e95b12..8a7212d9e 100644 --- a/codes/swift/chapter_stack_and_queue/linkedlist_queue.swift +++ b/codes/swift/chapter_stack_and_queue/linkedlist_queue.swift @@ -10,9 +10,11 @@ import utils 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 { diff --git a/codes/swift/chapter_stack_and_queue/linkedlist_stack.swift b/codes/swift/chapter_stack_and_queue/linkedlist_stack.swift index 7f857380c..24d4866a9 100644 --- a/codes/swift/chapter_stack_and_queue/linkedlist_stack.swift +++ b/codes/swift/chapter_stack_and_queue/linkedlist_stack.swift @@ -9,9 +9,11 @@ import utils /* 基于链表实现的栈 */ class LinkedListStack { private var _peek: ListNode? // 将头节点作为栈顶 - private var _size = 0 // 栈的长度 + private var _size: Int // 栈的长度 - init() {} + init() { + _size = 0 + } /* 获取栈的长度 */ func size() -> Int { @@ -51,8 +53,8 @@ class LinkedListStack { /* 将 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/codes/swift/chapter_tree/array_binary_tree.swift b/codes/swift/chapter_tree/array_binary_tree.swift index 8088712b2..18ebe41a2 100644 --- a/codes/swift/chapter_tree/array_binary_tree.swift +++ b/codes/swift/chapter_tree/array_binary_tree.swift @@ -48,7 +48,7 @@ class ArrayBinaryTree { 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/codes/swift/chapter_tree/avl_tree.swift b/codes/swift/chapter_tree/avl_tree.swift index a7f8dc865..52da21c13 100644 --- a/codes/swift/chapter_tree/avl_tree.swift +++ b/codes/swift/chapter_tree/avl_tree.swift @@ -10,10 +10,12 @@ import utils class AVLTree { fileprivate var root: TreeNode? // 根节点 + init() {} + /* 获取节点高度 */ func height(node: TreeNode?) -> Int { // 空节点高度为 -1 ,叶节点高度为 0 - node == nil ? -1 : node!.height + node?.height ?? -1 } /* 更新节点高度 */ @@ -132,7 +134,7 @@ class AVLTree { 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/codes/swift/chapter_tree/binary_search_tree.swift b/codes/swift/chapter_tree/binary_search_tree.swift index 580b6a176..51141e903 100644 --- a/codes/swift/chapter_tree/binary_search_tree.swift +++ b/codes/swift/chapter_tree/binary_search_tree.swift @@ -108,7 +108,7 @@ class BinarySearchTree { // 子节点数量 = 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 { diff --git a/codes/swift/utils/Vertex.swift b/codes/swift/utils/Vertex.swift index 025109a78..1eedf44fe 100644 --- a/codes/swift/utils/Vertex.swift +++ b/codes/swift/utils/Vertex.swift @@ -22,19 +22,11 @@ public class Vertex: Hashable { /* 输入值列表 vals ,返回顶点列表 vets */ public static func valsToVets(vals: [Int]) -> [Vertex] { - var vets: [Vertex] = [] - for val in vals { - vets.append(Vertex(val: val)) - } - return vets + vals.map { Vertex(val: $0) } } /* 输入顶点列表 vets ,返回值列表 vals */ public static func vetsToVals(vets: [Vertex]) -> [Int] { - var vals: [Int] = [] - for vet in vets { - vals.append(vet.val) - } - return vals + vets.map { $0.val } } } diff --git a/docs-en/chapter_computational_complexity/time_complexity.md b/docs-en/chapter_computational_complexity/time_complexity.md index 7d278997d..7dee459a1 100644 --- a/docs-en/chapter_computational_complexity/time_complexity.md +++ b/docs-en/chapter_computational_complexity/time_complexity.md @@ -317,7 +317,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) } } diff --git a/docs-en/chapter_data_structure/basic_data_types.md b/docs-en/chapter_data_structure/basic_data_types.md index 3aa4f4aa0..0eed870eb 100644 --- a/docs-en/chapter_data_structure/basic_data_types.md +++ b/docs-en/chapter_data_structure/basic_data_types.md @@ -101,10 +101,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/chapter_computational_complexity/time_complexity.md b/docs/chapter_computational_complexity/time_complexity.md index b7ee15386..812e97a73 100755 --- a/docs/chapter_computational_complexity/time_complexity.md +++ b/docs/chapter_computational_complexity/time_complexity.md @@ -317,7 +317,7 @@ $$ // 算法 C 的时间复杂度:常数阶 func algorithmC(n: Int) { - for _ in 0 ..< 1000000 { + for _ in 0 ..< 1_000_000 { print(0) } } diff --git a/docs/chapter_data_structure/basic_data_types.md b/docs/chapter_data_structure/basic_data_types.md index f349033e1..a504b9d45 100644 --- a/docs/chapter_data_structure/basic_data_types.md +++ b/docs/chapter_data_structure/basic_data_types.md @@ -101,10 +101,10 @@ ```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_heap/heap.md b/docs/chapter_heap/heap.md index f6904d5e2..5092430bc 100644 --- a/docs/chapter_heap/heap.md +++ b/docs/chapter_heap/heap.md @@ -270,7 +270,35 @@ === "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"