给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。
你可以假设数组中无重复元素。
https://leetcode-cn.com/problems/search-insert-position/
暴力解法
最简单的想法就是直接暴力搜索。
由于数组已经排好序了,我们只需要从小到大遍历一遍。如果目标值存在,则输出位置。如果不存在,返回比目标值大的第一个数字的位置即可。
这里就不详细写代码啦,相信大家都可以自己写出来。
时间复杂度分析:
我们将数组遍历了一遍,因此时间复杂度为 O(n)。
二分查找
实际上,遍历数组并没有很好地利用它有序的性质。
如果它是无序的,我们也可以通过遍历一遍数组来判断目标值是否在数组中。
对于一个有序数组,经常刷题的小伙伴首先想到的就是二分查找。它可以很好地利用数组有序的性质来进行查找。
如果你早就会二分查找,那后面的内容就不用看啦~
下面我会用递归来实现二分查找。
实际上递归的效率(主要是空间效率)并不高,但可以帮大家更好的理解算法的思想。
下面是具体步骤:
将目标值和数组的中间值进行对比
如果目标值和中间值相等,找到目标
如果目标值更小,意味着目标值在数组的左半区域,搜索左半数组
如果目标值更大,意味着目标值在数组的右半区域,搜索右半数组
搜索左/右半数组的时候依然采取二分查找的方式,即重复第一个步骤
如果你觉得这个过程有点抽象,那么看一下我写的代码吧~
def searchInsert(self, nums: List[int], target: int) -> int:
n = len(nums)
mid = n//2
# 边界条件
if n == 0:
return 0
if nums[mid] == target:
return mid
# 二分查找
# 如果目标值更大,意味着目标值在数组的右半区域,搜索右半数组
if nums[mid] < target:
return mid + 1 + self.searchInsert(nums[mid+1:],target)
# 如果目标值更小,意味着目标值在数组的左半区域,搜索左半数组
if nums[mid] > target:
return self.searchInsert(nums[:mid],target)
SearchInsert 是一个利用二分查找来搜索目标值的函数,搜索子数组的过程用递归来实现。
是不是和步骤中说的一模一样呢。
一般来说,大家会用 while 循环来实现二分查找,但思想和上面的递归是完全一样的。
时间复杂度分析的证明需要花点时间,所以这里就直接说结论。
二分查找的时间复杂度是 O(logn)。