From f49c6740299079d60196c106c59c5d05b72d3796 Mon Sep 17 00:00:00 2001 From: nuomi1 Date: Thu, 5 Jan 2023 21:16:05 +0800 Subject: [PATCH] feat: add Swift codes for array article --- codes/swift/Package.swift | 2 + .../chapter_array_and_linkedlist/array.swift | 103 ++++++++++++++++++ docs/chapter_array_and_linkedlist/array.md | 91 ++++++++++++++++ 3 files changed, 196 insertions(+) create mode 100644 codes/swift/chapter_array_and_linkedlist/array.swift diff --git a/codes/swift/Package.swift b/codes/swift/Package.swift index a292d9fd3..d9368354b 100644 --- a/codes/swift/Package.swift +++ b/codes/swift/Package.swift @@ -9,6 +9,7 @@ let package = Package( .executable(name: "worst_best_time_complexity", targets: ["worst_best_time_complexity"]), .executable(name: "space_complexity", targets: ["space_complexity"]), .executable(name: "leetcode_two_sum", targets: ["leetcode_two_sum"]), + .executable(name: "array", targets: ["array"]), ], targets: [ .target(name: "utils", path: "utils"), @@ -16,5 +17,6 @@ let package = Package( .executableTarget(name: "worst_best_time_complexity", path: "chapter_computational_complexity", sources: ["worst_best_time_complexity.swift"]), .executableTarget(name: "space_complexity", dependencies: ["utils"], path: "chapter_computational_complexity", sources: ["space_complexity.swift"]), .executableTarget(name: "leetcode_two_sum", path: "chapter_computational_complexity", sources: ["leetcode_two_sum.swift"]), + .executableTarget(name: "array", path: "chapter_array_and_linkedlist", sources: ["array.swift"]), ] ) diff --git a/codes/swift/chapter_array_and_linkedlist/array.swift b/codes/swift/chapter_array_and_linkedlist/array.swift new file mode 100644 index 000000000..c0c7ab9b9 --- /dev/null +++ b/codes/swift/chapter_array_and_linkedlist/array.swift @@ -0,0 +1,103 @@ +/** + * File: array.swift + * Created Time: 2023-01-05 + * Author: nuomi1 (nuomi1@qq.com) + */ + +// 随机返回一个数组元素 +func randomAccess(nums: [Int]) -> Int { + // 在区间 [0, nums.count) 中随机抽取一个数字 + let randomIndex = nums.indices.randomElement()! + // 获取并返回随机元素 + let randomNum = nums[randomIndex] + return randomNum +} + +// 扩展数组长度 +func extend(nums: [Int], enlarge: Int) -> [Int] { + // 初始化一个扩展长度后的数组 + var res = Array(repeating: 0, count: nums.count + enlarge) + // 将原数组中的所有元素复制到新数组 + for i in nums.indices { + res[i] = nums[i] + } + // 返回扩展后的新数组 + return res +} + +// 在数组的索引 index 处插入元素 num +func insert(nums: inout [Int], num: Int, index: Int) { + // 把索引 index 以及之后的所有元素向后移动一位 + for i in sequence(first: nums.count - 1, next: { $0 > index + 1 ? $0 - 1 : nil }) { + nums[i] = nums[i - 1] + } + // 将 num 赋给 index 处元素 + nums[index] = num +} + +// 删除索引 index 处元素 +func remove(nums: inout [Int], index: Int) { + let count = nums.count + // 把索引 index 之后的所有元素向前移动一位 + for i in sequence(first: index, next: { $0 < count - 1 - 1 ? $0 + 1 : nil }) { + nums[i] = nums[i + 1] + } +} + +// 遍历数组 +func traverse(nums: [Int]) { + var count = 0 + // 通过索引遍历数组 + for _ in nums.indices { + count += 1 + } + // 直接遍历数组 + for _ in nums { + count += 1 + } +} + +// 在数组中查找指定元素 +func find(nums: [Int], target: Int) -> Int { + for i in nums.indices { + if nums[i] == target { + return i + } + } + return -1 +} + +@main +enum _Array { + // Driver Code + static func main() { + // 初始化数组 + let arr = Array(repeating: 0, count: 5) + print("数组 arr = \(arr)") + var nums = [1, 3, 2, 5, 4] + print("数组 nums = \(nums)") + + // 随机访问 + let randomNum = randomAccess(nums: nums) + print("在 nums 中获取随机元素 \(randomNum)") + + // 长度扩展 + nums = extend(nums: nums, enlarge: 3) + print("将数组长度扩展至 8 ,得到 nums = \(nums)") + + // 插入元素 + insert(nums: &nums, num: 6, index: 3) + print("在索引 3 处插入数字 6 ,得到 nums = \(nums)") + + // 删除元素 + remove(nums: &nums, index: 2) + print("删除索引 2 处的元素,得到 nums = \(nums)") + + // 遍历数组 + traverse(nums: nums) + + // 查找元素 + let index = find(nums: nums, target: 3) + print("在 nums 中查找元素 3 ,得到索引 = \(index)") + } +} diff --git a/docs/chapter_array_and_linkedlist/array.md b/docs/chapter_array_and_linkedlist/array.md index 648a9c753..5e814ea24 100644 --- a/docs/chapter_array_and_linkedlist/array.md +++ b/docs/chapter_array_and_linkedlist/array.md @@ -81,6 +81,14 @@ comments: true int[] nums = { 1, 3, 2, 5, 4 }; ``` +=== "Swift" + + ```swift title="array.swift" + // 初始化数组 + let arr = Array(repeating: 0, count: 5) // [0, 0, 0, 0, 0] + let nums = [1, 3, 2, 5, 4] + ``` + ## 数组优点 **在数组中访问元素非常高效。** 这是因为在数组中,计算元素的内存地址非常容易。给定数组首个元素的地址、和一个元素的索引,利用以下公式可以直接计算得到该元素的内存地址,从而直接访问此元素。 @@ -193,6 +201,19 @@ elementAddr = firtstElementAddr + elementLength * elementIndex } ``` +=== "Swift" + + ```swift title="array.swift" + // 随机返回一个数组元素 + func randomAccess(nums: [Int]) -> Int { + // 在区间 [0, nums.count) 中随机抽取一个数字 + let randomIndex = nums.indices.randomElement()! + // 获取并返回随机元素 + let randomNum = nums[randomIndex] + return randomNum + } + ``` + ## 数组缺点 **数组在初始化后长度不可变。** 由于系统无法保证数组之后的内存空间是可用的,因此数组长度无法扩展。而若希望扩容数组,则需新建一个数组,然后把原数组元素依次拷贝到新数组,在数组很大的情况下,这是非常耗时的。 @@ -317,6 +338,22 @@ elementAddr = firtstElementAddr + elementLength * elementIndex } ``` +=== "Swift" + + ```swift title="array.swift" + // 扩展数组长度 + func extend(nums: [Int], enlarge: Int) -> [Int] { + // 初始化一个扩展长度后的数组 + var res = Array(repeating: 0, count: nums.count + enlarge) + // 将原数组中的所有元素复制到新数组 + for i in nums.indices { + res[i] = nums[i] + } + // 返回扩展后的新数组 + return res + } + ``` + **数组中插入或删除元素效率低下。** 假设我们想要在数组中间某位置插入一个元素,由于数组元素在内存中是“紧挨着的”,它们之间没有空间再放任何数据。因此,我们不得不将此索引之后的所有元素都向后移动一位,然后再把元素赋值给该索引。删除元素也是类似,需要把此索引之后的元素都向前移动一位。总体看有以下缺点: - **时间复杂度高:** 数组的插入和删除的平均时间复杂度均为 $O(N)$ ,其中 $N$ 为数组长度。 @@ -486,6 +523,29 @@ elementAddr = firtstElementAddr + elementLength * elementIndex } ``` +=== "Swift" + + ```swift title="array.swift" + // 在数组的索引 index 处插入元素 num + func insert(nums: inout [Int], num: Int, index: Int) { + // 把索引 index 以及之后的所有元素向后移动一位 + for i in sequence(first: nums.count - 1, next: { $0 > index + 1 ? $0 - 1 : nil }) { + nums[i] = nums[i - 1] + } + // 将 num 赋给 index 处元素 + nums[index] = num + } + + // 删除索引 index 处元素 + func remove(nums: inout [Int], index: Int) { + let count = nums.count + // 把索引 index 之后的所有元素向前移动一位 + for i in sequence(first: index, next: { $0 < count - 1 - 1 ? $0 + 1 : nil }) { + nums[i] = nums[i + 1] + } + } + ``` + ## 数组常用操作 **数组遍历。** 以下介绍两种常用的遍历方法。 @@ -611,6 +671,23 @@ elementAddr = firtstElementAddr + elementLength * elementIndex } ``` +=== "Swift" + + ```swift title="array.swift" + // 遍历数组 + func traverse(nums: [Int]) { + var count = 0 + // 通过索引遍历数组 + for _ in nums.indices { + count += 1 + } + // 直接遍历数组 + for _ in nums { + count += 1 + } + } + ``` + **数组查找。** 通过遍历数组,查找数组内的指定元素,并输出对应索引。 === "Java" @@ -713,6 +790,20 @@ elementAddr = firtstElementAddr + elementLength * elementIndex } ``` +=== "Swift" + + ```swift title="array.swift" + // 在数组中查找指定元素 + func find(nums: [Int], target: Int) -> Int { + for i in nums.indices { + if nums[i] == target { + return i + } + } + return -1 + } + ``` + ## 数组典型应用 **随机访问。** 如果我们想要随机抽取一些样本,那么可以用数组存储,并生成一个随机序列,根据索引实现样本的随机抽取。