14. 二分查找
描述
给定一个排序的整数数组(升序)和一个要查找的整数target
,用O(logn)
的时间查找到target第一次出现的下标(从0开始),如果target不存在于数组中,返回-1
。
您在真实的面试中是否遇到过这个题? 是
题目纠错
样例
在数组 [1, 2, 3, 3, 4, 5, 10]
中二分查找3
,返回2
。
挑战
如果数组中的整数个数超过了2^32,你的算法是否会出错?
14. First Position of Target
Description
For a given sorted array (ascending order) and a target
number, find the first index of this number in O(log n)
time complexity.
If the target number does not exist in the array, return -1
.
Have you met this question in a real interview? Yes
Problem Correction
Example
If the array is [1, 2, 3, 3, 4, 5, 10]
, for given target 3
, return 2
.
Challenge
If the count of numbers is bigger than 2^32, can your code work properly?
二分查找使用迭代永远不会发生栈溢出
看代码吧,记得看最后的备注
#用迭代实现二分法
#写个类吧
class Solution:
def binarySearch(self, nums, target):
return self.search(nums, 0, len(nums) - 1, target)
def search(self, nums, start, end, target):
if start > end:
return -1
#start, end = 0, len(nums) -1
mid = (start + end)//2
if nums[mid] > target:
return self.search(nums, start, mid, target)
if nums[mid] == target:
return mid
if nums[mid] < target:
return self.search(nums, mid, end, target)
my_solution = Solution()
nums = [1,2,3,4,5,6]
target = 2
#start, end = 0, len(nums) -1
targetIndex = my_solution.binarySearch(nums, target)
print(targetIndex)
'''
#用迭代实现二分法
#写个函数吧
def search(nums, start, end, target):
if start > end:
return -1
#start, end = 0, len(nums) -1
mid = (start + end)//2
if nums[mid] > target:
return search(nums, start, mid, target)
if nums[mid] == target:
return mid
if nums[mid] < target:
return search(nums, mid, end, target)
#my_solution = Solution()
nums = [1,2,3,4,5,6]
target = 2
start, end = 0, len(nums) -1
targetIndex = search(nums, start, end, target)
print(targetIndex)
'''
#二分法,模板实现
class Solution:
def binarySearch(self, nums, target):
if len(nums) == 0:
return -1
start, end = 0, len(nums) -1
while (start + 1 < end):
mid = (start + end) // 2
if nums[mid] < target:
start = mid
else:
end = mid
'''
这里不能画蛇添足,要不然错了,如果碰到nums[mid] == target情况,
end = mid, nums[end]= nums[mid] == target, 跳转到最后,return end了
elif nums[mid] > tartet:
end = mid
else:
return mid
'''
if nums[start] == target:
return start
if nums[end] == target:
return end
return -1
my_solution = Solution()
nums = [1,2,3,4,5,6]
target = 2
targetIndex = my_solution.binarySearch(nums, target)
print(targetIndex)
为什么要用 start + 1 < end?而不是 start < end 或者 start <= end?
A: 为了避免死循环。二分法的模板中,整个程序架构分为两个部分:
- 通过 while 循环,将区间范围从 n 缩小到 2 (只有 start 和 end 两个点)。
- 在 start 和 end 中判断是否有解。
start < end 或者 start <= end 在寻找目标最后一次出现的位置的时候,出现死循环。
Q: 为什么明明可以 start = mid + 1 偏偏要写成 start = mid?
A: 大部分时候,mid 是可以 +1 和 -1 的。在一些特殊情况下,比如寻找目标的最后一次出现的位置时,当 target 与 nums[mid] 相等的时候,是不能够使用 mid + 1 或者 mid - 1 的。因为会导致漏掉解。那么为了节省脑力
,统一写成 start = mid / end = mid 并不会造成任何解的丢失,并且也不会损失效率——log(n) 和 log(n+1) 没有区别。
认识你是我们的缘分,同学,等等,记得关注我。
微信扫一扫
关注该公众号