题目描述
给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。
解题
要解决这个问题,我们可以使用二分查找算法。二分查找是一种高效的查找算法,时间复杂度为 O(log n),适用于有序数组。我们需要找到目标值在数组中的位置,如果目标值不存在,则找到它应该插入的位置。
具体步骤如下:
- 初始化左右指针
left
和right
。 - 进行循环,直到
left
超过right
:- 计算中间位置
mid
。 - 如果
nums[mid]
等于目标值,返回mid
。 - 如果
nums[mid]
小于目标值,将left
更新为mid + 1
。 - 如果
nums[mid]
大于目标值,将right
更新为mid - 1
。
- 计算中间位置
- 循环结束后,如果没有找到目标值,返回
left
,它表示目标值应该插入的位置。
以下是完整的 Swift 代码实现:
class Solution {
func searchInsert(_ nums: [Int], _ target: Int) -> Int {
var left = 0
var right = nums.count - 1
while left <= right {
let mid = left + (right - left) / 2
if nums[mid] == target {
return mid
} else if nums[mid] < target {
left = mid + 1
} else {
right = mid - 1
}
}
// 为什么是 left, 而不是任何其它值 ?
return left
}
}
解释:
- 初始化:设置左指针
left
为 0,右指针right
为数组的最后一个索引nums.count - 1
。 - 二分查找:在
left
小于等于right
的情况下,计算中间位置mid
。比较nums[mid]
与目标值target
:- 如果相等,返回
mid
。 - 如果
nums[mid]
小于目标值,将左指针left
移动到mid + 1
。 - 如果
nums[mid]
大于目标值,将右指针right
移动到mid - 1
。
- 如果相等,返回
- 返回结果:如果没有找到目标值,最终
left
的值就是目标值应该插入的位置。
这个算法保证了在 O(log n)
时间复杂度内找到目标值或插入位置,非常高效。
跳出 while 循环后,为什么 return left 而不是 return right 或者 return 其它 ?
当 while
循环结束,说明目标不在数组中,left
指针的位置就是目标值应该插入的位置。下面是详细解释:
-
目标值存在于数组中:
- 在这种情况下,我们在循环中会找到目标值,并且直接返回目标值的索引
mid
,循环提前结束。
- 在这种情况下,我们在循环中会找到目标值,并且直接返回目标值的索引
-
目标值不存在于数组中:
- 如果目标值小于数组中的所有元素,则
left
会最终停在数组的起始位置,即0
。 - 如果目标值大于数组中的所有元素,则
left
会最终停在数组的末尾位置,即nums.count
。 - 如果目标值在数组中的某两个元素之间,则
left
会停在它应该插入的位置。
- 如果目标值小于数组中的所有元素,则