mirror of
https://github.com/krahets/hello-algo.git
synced 2024-12-26 12:56:32 +08:00
feat: add Swift codes for chapter_searching articles (#309)
* feat: add Swift codes for linear_search article * feat: add Swift codes for binary_search article * feat: add Swift codes for hashing_search article
This commit is contained in:
parent
15c798046a
commit
1665fe176c
8 changed files with 261 additions and 7 deletions
|
@ -28,6 +28,9 @@ let package = Package(
|
||||||
.executable(name: "binary_search_tree", targets: ["binary_search_tree"]),
|
.executable(name: "binary_search_tree", targets: ["binary_search_tree"]),
|
||||||
.executable(name: "avl_tree", targets: ["avl_tree"]),
|
.executable(name: "avl_tree", targets: ["avl_tree"]),
|
||||||
.executable(name: "my_heap", targets: ["my_heap"]),
|
.executable(name: "my_heap", targets: ["my_heap"]),
|
||||||
|
.executable(name: "linear_search", targets: ["linear_search"]),
|
||||||
|
.executable(name: "binary_search", targets: ["binary_search"]),
|
||||||
|
.executable(name: "hashing_search", targets: ["hashing_search"]),
|
||||||
],
|
],
|
||||||
targets: [
|
targets: [
|
||||||
.target(name: "utils", path: "utils"),
|
.target(name: "utils", path: "utils"),
|
||||||
|
@ -54,5 +57,8 @@ let package = Package(
|
||||||
.executableTarget(name: "binary_search_tree", dependencies: ["utils"], path: "chapter_tree", sources: ["binary_search_tree.swift"]),
|
.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"]),
|
.executableTarget(name: "avl_tree", dependencies: ["utils"], path: "chapter_tree", sources: ["avl_tree.swift"]),
|
||||||
.executableTarget(name: "my_heap", dependencies: ["utils"], path: "chapter_heap", sources: ["my_heap.swift"]),
|
.executableTarget(name: "my_heap", dependencies: ["utils"], path: "chapter_heap", sources: ["my_heap.swift"]),
|
||||||
|
.executableTarget(name: "linear_search", dependencies: ["utils"], path: "chapter_searching", sources: ["linear_search.swift"]),
|
||||||
|
.executableTarget(name: "binary_search", path: "chapter_searching", sources: ["binary_search.swift"]),
|
||||||
|
.executableTarget(name: "hashing_search", dependencies: ["utils"], path: "chapter_searching", sources: ["hashing_search.swift"]),
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
62
codes/swift/chapter_searching/binary_search.swift
Normal file
62
codes/swift/chapter_searching/binary_search.swift
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
/**
|
||||||
|
* File: binary_search.swift
|
||||||
|
* Created Time: 2023-01-28
|
||||||
|
* Author: nuomi1 (nuomi1@qq.com)
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* 二分查找(双闭区间) */
|
||||||
|
func binarySearch(nums: [Int], target: Int) -> Int {
|
||||||
|
// 初始化双闭区间 [0, n-1] ,即 i, j 分别指向数组首元素、尾元素
|
||||||
|
var i = 0
|
||||||
|
var j = nums.count - 1
|
||||||
|
// 循环,当搜索区间为空时跳出(当 i > j 时为空)
|
||||||
|
while i <= j {
|
||||||
|
let m = (i + j) / 2 // 计算中点索引 m
|
||||||
|
if nums[m] < target { // 此情况说明 target 在区间 [m+1, j] 中
|
||||||
|
i = m + 1
|
||||||
|
} else if nums[m] > target { // 此情况说明 target 在区间 [i, m-1] 中
|
||||||
|
j = m - 1
|
||||||
|
} else { // 找到目标元素,返回其索引
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 未找到目标元素,返回 -1
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 二分查找(左闭右开) */
|
||||||
|
func binarySearch1(nums: [Int], target: Int) -> Int {
|
||||||
|
// 初始化左闭右开 [0, n) ,即 i, j 分别指向数组首元素、尾元素+1
|
||||||
|
var i = 0
|
||||||
|
var j = nums.count
|
||||||
|
// 循环,当搜索区间为空时跳出(当 i = j 时为空)
|
||||||
|
while i < j {
|
||||||
|
let m = (i + j) / 2 // 计算中点索引 m
|
||||||
|
if nums[m] < target { // 此情况说明 target 在区间 [m+1, j) 中
|
||||||
|
i = m + 1
|
||||||
|
} else if nums[m] > target { // 此情况说明 target 在区间 [i, m) 中
|
||||||
|
j = m
|
||||||
|
} else { // 找到目标元素,返回其索引
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 未找到目标元素,返回 -1
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
@main
|
||||||
|
enum BinarySearch {
|
||||||
|
/* Driver Code */
|
||||||
|
static func main() {
|
||||||
|
let target = 6
|
||||||
|
let nums = [1, 3, 6, 8, 12, 15, 23, 67, 70, 92]
|
||||||
|
|
||||||
|
/* 二分查找(双闭区间) */
|
||||||
|
var index = binarySearch(nums: nums, target: target)
|
||||||
|
print("目标元素 6 的索引 = \(index)")
|
||||||
|
|
||||||
|
/* 二分查找(左闭右开) */
|
||||||
|
index = binarySearch1(nums: nums, target: target)
|
||||||
|
print("目标元素 6 的索引 = \(index)")
|
||||||
|
}
|
||||||
|
}
|
50
codes/swift/chapter_searching/hashing_search.swift
Normal file
50
codes/swift/chapter_searching/hashing_search.swift
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
/**
|
||||||
|
* File: hashing_search.swift
|
||||||
|
* Created Time: 2023-01-28
|
||||||
|
* Author: nuomi1 (nuomi1@qq.com)
|
||||||
|
*/
|
||||||
|
|
||||||
|
import utils
|
||||||
|
|
||||||
|
/* 哈希查找(数组) */
|
||||||
|
func hashingSearch(map: [Int: Int], target: Int) -> Int {
|
||||||
|
// 哈希表的 key: 目标元素,value: 索引
|
||||||
|
// 若哈希表中无此 key ,返回 -1
|
||||||
|
return map[target, default: -1]
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 哈希查找(链表) */
|
||||||
|
func hashingSearch1(map: [Int: ListNode], target: Int) -> ListNode? {
|
||||||
|
// 哈希表的 key: 目标结点值,value: 结点对象
|
||||||
|
// 若哈希表中无此 key ,返回 null
|
||||||
|
return map[target]
|
||||||
|
}
|
||||||
|
|
||||||
|
@main
|
||||||
|
enum HashingSearch {
|
||||||
|
/* Driver Code */
|
||||||
|
static func main() {
|
||||||
|
let target = 3
|
||||||
|
|
||||||
|
/* 哈希查找(数组) */
|
||||||
|
let nums = [1, 5, 3, 2, 4, 7, 5, 9, 10, 8]
|
||||||
|
// 初始化哈希表
|
||||||
|
var map: [Int: Int] = [:]
|
||||||
|
for i in nums.indices {
|
||||||
|
map[nums[i]] = i // key: 元素,value: 索引
|
||||||
|
}
|
||||||
|
let index = hashingSearch(map: map, target: target)
|
||||||
|
print("目标元素 3 的索引 = \(index)")
|
||||||
|
|
||||||
|
/* 哈希查找(链表) */
|
||||||
|
var head = ListNode.arrToLinkedList(arr: nums)
|
||||||
|
// 初始化哈希表
|
||||||
|
var map1: [Int: ListNode] = [:]
|
||||||
|
while head != nil {
|
||||||
|
map1[head!.val] = head! // key: 结点值,value: 结点
|
||||||
|
head = head?.next
|
||||||
|
}
|
||||||
|
let node = hashingSearch1(map: map1, target: target)
|
||||||
|
print("目标结点值 3 的对应结点对象为 \(node!)")
|
||||||
|
}
|
||||||
|
}
|
53
codes/swift/chapter_searching/linear_search.swift
Normal file
53
codes/swift/chapter_searching/linear_search.swift
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
/**
|
||||||
|
* File: linear_search.swift
|
||||||
|
* Created Time: 2023-01-28
|
||||||
|
* Author: nuomi1 (nuomi1@qq.com)
|
||||||
|
*/
|
||||||
|
|
||||||
|
import utils
|
||||||
|
|
||||||
|
/* 线性查找(数组) */
|
||||||
|
func linearSearch(nums: [Int], target: Int) -> Int {
|
||||||
|
// 遍历数组
|
||||||
|
for i in nums.indices {
|
||||||
|
// 找到目标元素,返回其索引
|
||||||
|
if nums[i] == target {
|
||||||
|
return i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 未找到目标元素,返回 -1
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 线性查找(链表) */
|
||||||
|
func linearSearch(head: ListNode?, target: Int) -> ListNode? {
|
||||||
|
var head = head
|
||||||
|
// 遍历链表
|
||||||
|
while head != nil {
|
||||||
|
// 找到目标结点,返回之
|
||||||
|
if head?.val == target {
|
||||||
|
return head
|
||||||
|
}
|
||||||
|
head = head?.next
|
||||||
|
}
|
||||||
|
// 未找到目标结点,返回 null
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
@main
|
||||||
|
enum LinearSearch {
|
||||||
|
/* Driver Code */
|
||||||
|
static func main() {
|
||||||
|
let target = 3
|
||||||
|
|
||||||
|
/* 在数组中执行线性查找 */
|
||||||
|
let nums = [1, 5, 3, 2, 4, 7, 5, 9, 10, 8]
|
||||||
|
let index = linearSearch(nums: nums, target: target)
|
||||||
|
print("目标元素 3 的索引 = \(index)")
|
||||||
|
|
||||||
|
/* 在链表中执行线性查找 */
|
||||||
|
let head = ListNode.arrToLinkedList(arr: nums)
|
||||||
|
let node = linearSearch(head: head, target: target)
|
||||||
|
print("目标结点值 3 的对应结点对象为 \(node!)")
|
||||||
|
}
|
||||||
|
}
|
|
@ -11,4 +11,14 @@ public class ListNode {
|
||||||
public init(x: Int) {
|
public init(x: Int) {
|
||||||
val = x
|
val = x
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static func arrToLinkedList(arr: [Int]) -> ListNode? {
|
||||||
|
let dum = ListNode(x: 0)
|
||||||
|
var head: ListNode? = dum
|
||||||
|
for val in arr {
|
||||||
|
head?.next = ListNode(x: val)
|
||||||
|
head = head?.next
|
||||||
|
}
|
||||||
|
return dum.next
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -213,7 +213,25 @@ $$
|
||||||
=== "Swift"
|
=== "Swift"
|
||||||
|
|
||||||
```swift title="binary_search.swift"
|
```swift title="binary_search.swift"
|
||||||
|
/* 二分查找(双闭区间) */
|
||||||
|
func binarySearch(nums: [Int], target: Int) -> Int {
|
||||||
|
// 初始化双闭区间 [0, n-1] ,即 i, j 分别指向数组首元素、尾元素
|
||||||
|
var i = 0
|
||||||
|
var j = nums.count - 1
|
||||||
|
// 循环,当搜索区间为空时跳出(当 i > j 时为空)
|
||||||
|
while i <= j {
|
||||||
|
let m = (i + j) / 2 // 计算中点索引 m
|
||||||
|
if nums[m] < target { // 此情况说明 target 在区间 [m+1, j] 中
|
||||||
|
i = m + 1
|
||||||
|
} else if nums[m] > target { // 此情况说明 target 在区间 [i, m-1] 中
|
||||||
|
j = m - 1
|
||||||
|
} else { // 找到目标元素,返回其索引
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 未找到目标元素,返回 -1
|
||||||
|
return -1
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### “左闭右开”实现
|
### “左闭右开”实现
|
||||||
|
@ -383,7 +401,25 @@ $$
|
||||||
=== "Swift"
|
=== "Swift"
|
||||||
|
|
||||||
```swift title="binary_search.swift"
|
```swift title="binary_search.swift"
|
||||||
|
/* 二分查找(左闭右开) */
|
||||||
|
func binarySearch1(nums: [Int], target: Int) -> Int {
|
||||||
|
// 初始化左闭右开 [0, n) ,即 i, j 分别指向数组首元素、尾元素+1
|
||||||
|
var i = 0
|
||||||
|
var j = nums.count
|
||||||
|
// 循环,当搜索区间为空时跳出(当 i = j 时为空)
|
||||||
|
while i < j {
|
||||||
|
let m = (i + j) / 2 // 计算中点索引 m
|
||||||
|
if nums[m] < target { // 此情况说明 target 在区间 [m+1, j) 中
|
||||||
|
i = m + 1
|
||||||
|
} else if nums[m] > target { // 此情况说明 target 在区间 [i, m) 中
|
||||||
|
j = m
|
||||||
|
} else { // 找到目标元素,返回其索引
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 未找到目标元素,返回 -1
|
||||||
|
return -1
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### 两种表示对比
|
### 两种表示对比
|
||||||
|
@ -475,7 +511,10 @@ $$
|
||||||
=== "Swift"
|
=== "Swift"
|
||||||
|
|
||||||
```swift title=""
|
```swift title=""
|
||||||
|
// (i + j) 有可能超出 int 的取值范围
|
||||||
|
let m = (i + j) / 2
|
||||||
|
// 更换为此写法则不会越界
|
||||||
|
let m = i + (j - 1) / 2
|
||||||
```
|
```
|
||||||
|
|
||||||
## 复杂度分析
|
## 复杂度分析
|
||||||
|
|
|
@ -108,7 +108,12 @@ comments: true
|
||||||
=== "Swift"
|
=== "Swift"
|
||||||
|
|
||||||
```swift title="hashing_search.swift"
|
```swift title="hashing_search.swift"
|
||||||
|
/* 哈希查找(数组) */
|
||||||
|
func hashingSearch(map: [Int: Int], target: Int) -> Int {
|
||||||
|
// 哈希表的 key: 目标元素,value: 索引
|
||||||
|
// 若哈希表中无此 key ,返回 -1
|
||||||
|
return map[target, default: -1]
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
再比如,如果我们想要给定一个目标结点值 `target` ,获取对应的链表结点对象,那么也可以使用哈希查找实现。
|
再比如,如果我们想要给定一个目标结点值 `target` ,获取对应的链表结点对象,那么也可以使用哈希查找实现。
|
||||||
|
@ -208,7 +213,12 @@ comments: true
|
||||||
=== "Swift"
|
=== "Swift"
|
||||||
|
|
||||||
```swift title="hashing_search.swift"
|
```swift title="hashing_search.swift"
|
||||||
|
/* 哈希查找(链表) */
|
||||||
|
func hashingSearch1(map: [Int: ListNode], target: Int) -> ListNode? {
|
||||||
|
// 哈希表的 key: 目标结点值,value: 结点对象
|
||||||
|
// 若哈希表中无此 key ,返回 null
|
||||||
|
return map[target]
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## 复杂度分析
|
## 复杂度分析
|
||||||
|
|
|
@ -136,7 +136,18 @@ comments: true
|
||||||
=== "Swift"
|
=== "Swift"
|
||||||
|
|
||||||
```swift title="linear_search.swift"
|
```swift title="linear_search.swift"
|
||||||
|
/* 线性查找(数组) */
|
||||||
|
func linearSearch(nums: [Int], target: Int) -> Int {
|
||||||
|
// 遍历数组
|
||||||
|
for i in nums.indices {
|
||||||
|
// 找到目标元素,返回其索引
|
||||||
|
if nums[i] == target {
|
||||||
|
return i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 未找到目标元素,返回 -1
|
||||||
|
return -1
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
再比如,我们想要在给定一个目标结点值 `target` ,返回此结点对象,也可以在链表中进行线性查找。
|
再比如,我们想要在给定一个目标结点值 `target` ,返回此结点对象,也可以在链表中进行线性查找。
|
||||||
|
@ -270,7 +281,20 @@ comments: true
|
||||||
=== "Swift"
|
=== "Swift"
|
||||||
|
|
||||||
```swift title="linear_search.swift"
|
```swift title="linear_search.swift"
|
||||||
|
/* 线性查找(链表) */
|
||||||
|
func linearSearch(head: ListNode?, target: Int) -> ListNode? {
|
||||||
|
var head = head
|
||||||
|
// 遍历链表
|
||||||
|
while head != nil {
|
||||||
|
// 找到目标结点,返回之
|
||||||
|
if head?.val == target {
|
||||||
|
return head
|
||||||
|
}
|
||||||
|
head = head?.next
|
||||||
|
}
|
||||||
|
// 未找到目标结点,返回 null
|
||||||
|
return nil
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## 复杂度分析
|
## 复杂度分析
|
||||||
|
|
Loading…
Reference in a new issue