二分查找中的小细节
主要参考《代码随想录》
力扣链接:704. 二分查找
二分查找,虽然思想非常简单,但是边界值的处理经常出问题。主要有以下两个方面:
例如到底是 while(left < right)
还是 while(left <= right)
,到底是right = middle
呢,还是要right = middle - 1
呢?
其实这两种方法都可以实现,选择哪种写法关键在于区间是如何定义的。
写二分法,区间的定义一般为两种,左闭右闭即[left, right],或者左闭右开即[left, right)。
举个例子,比如说有一个数组名为nums = [2,3,5,1,4]
那么以下写法为左闭右开:
nums = [2,3,5,1,4]
left = 0
right = len(nums)
#left = 0,right = 5
数组的合法下标是0,1,2,3,4.并不能取到5,所以是左闭右开区间。
同理,以下写法是左闭右闭区间
nums = [2,3,5,1,4]
left = 0
right = len(nums) - 1
#left = 0,right = 4
在后续的代码中,都要保持区间的一致性。
左闭右开区间
对于左闭右开区间,left == right
是不合法的,所以在while中写的时候应该写为while(left < right)
而在mid更新时,由于mid已经被检验过,肯定在区间外。所以若需更新left:left = mid+1
,若需更新right:right = mid
class Solution:
def search(self, nums: List[int], target: int) -> int:
begin = 0
end = len(nums)
mid = (begin+end)//2
while(begin<end):
if(nums[mid] == target):
return mid
elif nums[mid]>target:
end = mid
else:
begin = mid + 1
mid = (begin+end)//2
return -1
左闭右闭区间
对于左闭右闭区间,left == right
是合法的,所以在while中应该写为:while(left <= right)
而在mid更新时,由于mid已经被检验过,肯定在区间外。所以若需更新left:left = mid+1
,若需更新right:right = mid-1
class Solution:
def search(self, nums: List[int], target: int) -> int:
begin = 0
end = len(nums)-1
mid = (begin+end)//2
while(begin<=end):
if(nums[mid] == target):
return mid
elif nums[mid]>target:
end = mid - 1
else:
begin = mid + 1
mid = (begin+end)//2
return -1