给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。
你可以假设数组中无重复元素。
示例 1:
输入: [1,3,5,6], 5
输出: 2
示例 2:输入: [1,3,5,6], 2
输出: 1
示例 3:输入: [1,3,5,6], 7
输出: 4
示例 4:输入: [1,3,5,6], 0
输出: 0来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/search-insert-position
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
先想到用二分查找,递归实现,由于递归需要在传参时传入low和high,但函数原型里没有这2个参数,所以没写递归方式。查了下下面是迭代实现。
前提是升序且无重复元素,下面的代码有重复元素时可能返回的不是第一次出现的位置。
找不到时返回low的原因:
target小于整个原区间时,low一直为0不变,若最终未找到,则应插入到下标为0的位置,这个位置也是low的位置;
target大于整个原区间时,high一直为最后一个元素不变,若最终未找到,则应插入到最后一个元素的后面,此时循环因low>high而终止,即此时low在high后面,这时low的位置就是要插入的位置;
target属于某个中间区间时,若最终未找到,最后区间内剩2个元素。一种情况是low和mid和high相等,且target大于它们,则low的值变为mid+1,此时因low>high导致循环终止,因这时low的位置是target第一次大于某元素的位置,即要插入的位置,所以返回low;另一种情况是low和mid的值相同且mid>target,所以high的值变为mid-1,导致low>high,循环终止,因mid是第一个大于target的位置,且low和mid相等,所以这时low的位置就是要插入的位置。
def binary_search(nums,target):
low=0
high=len(nums)-1
while low<=high:
mid=(low+high)//2
if target<nums[mid]:
high=mid-1
elif target>nums[mid]:
low=mid+1
elif target==nums[mid]:
return mid
return low
nums=[1,3,5,7,9]
for i in [0,1,2,8,9,10]:
print(binary_search(nums,i))
题解中看到的一些知识:
1.链接中作者对评论的回复
因为计算机位数是有限的,假如first和last都没有溢出,如果使用 mid=(first+last)/2 的写法,first+last是有可能溢出的,而使用 mid=first+(last-first)/2 的写法就不会溢出。
假设全都为int型,上限为65535,first=45535,last=20001。则计算 mid=(first+last)/2 时会先计算括号里的数得到65536溢出了。而使用 mid=first+(last-first)/2 可以避免这种情况而达到相同的效果。
2.链接
mid=(left+right)//2, left+right 在Python中如果发生整型溢出,Python会自动转成长整形
3. 2的链接中,while low<high 的写法不懂,又查到其他资料。
4.python自带函数可以直接实现
链接,会修改原始数据
def searchInsert(nums, target):
nums.append(target) # 不管这个数在不在里面,直接append
nums.sort() # 然后再排序
return nums.index(target) # 最后返回查找的index
import bisect
def searchInsert(nums,target):
left = bisect.bisect_left(nums,target)
return left