原理解析
在有序的数组中查找特定元素的搜索
问题描述:
从一列有序的数组中查找是否包含27
[4, 13, 38, 49, 55, 65, 76, 97]
代码:
//二分搜索
//假设nums是一个升序数组
func p_binarySearch(nums: [Int], target: Int) -> Bool {
var left = 0, mid = 0, right = nums.count - 1
while left <= right {
mid = (right - left) / 2 + left
if nums[mid] == target {
return true
} else if nums[mid] < target {
left = mid + 1
} else {
right = mid - 1
}
}
return false
}
测试:
@objc func binarySearch()
{
//在数组中查找是否包含27
let binarySearchArray = [4, 13, 38, 49, 55, 65, 76, 97]
let result = p_binarySearch(nums: binarySearchArray, target: 27)
print(result)
}
结果:
false
注意细节
- mid 被定义在While 循环外面,如果被定义在里面,则每次循环都要重新给mid 分配内存空间,从而造成不必要的浪费;而被定义在循环外面,每次循环只要重新赋值
- 每次给每次重新给 mid 赋值不能写成mid = (right + left) / 2。这种写法表面上看没有问题,但当数组的长度非常大,算法又已经搜索到了最右边部分的时候那么right + left就会非常之大,造成溢出导致程序崩溃。所以解决问题的办法是写成 mid = (right - left) / 2 + left
当然,我们可以用递归来实现二分搜索:
func binarySearch(nums: [Int], target: Int) -> Bool {
return binarySearch(nums: nums, target: target, left: 0, right: nums.count - 1)
}
func binarySearch(nums: [Int], target: Int, left: Int, right: Int) -> Bool {
guard left <= right else {
return false
}
let mid = (right - left) / 2 + left
if nums[mid] == target {
return true
} else if nums[mid] < target {
return binarySearch(nums: nums, target: target, left: mid + 1, right: right)
} else {
return binarySearch(nums: nums, target: target, left: left, right: mid - 1)
}
}