二分查找易混淆的几个点(python)

二分查找是个很基础有很常用的算法,虽然他的代码很简单,但是其中却有几个十分容易混乱的地方,尤其是看不同教材或不同人写的二分代码,会有一些微小但关键的差异,自己写的时候也容易出错,写下这篇博客,主要为了将来自己糊涂时查阅,如果能帮助到其他人,那就是功德一件了。

代码

	def BinarySearch(nums:list, target:int)->int:
	'''
	nums是一个有序的整形列表,target是一个整数。该函数用于查找target在nums中是否存在,如果存在返回其在列表中的下标,如果不存在返回-1
	'''
	left, right = 0, len(nums)#思考1:为什么这里是len(nums)而不是len(nums)-1
	
	'''
	知识点:运算符//
	又叫地板初,自然是商向下取整,如15//2 = 7
	'''
	while left < right:#思考3:这里为什么是严格小于而非小于等于
		mid = left + (right - left) // 2#思考2:为什么这里写成此种格式而非更简洁的mid = (left + right) // 2
		if nums[mid] > target:
			right = mid 
		elif nums[mid] < target:
			left = mid + 1#思考4:为什么上面right不需要+1而left需要+1
		else:
			return mid
	return -1

思考题解答:

首先二分法的核心要义在于搞清楚区间,并保持一致:即究竟是在哪一个区间内进行的搜索,左右端点的开闭情况尤其需要注意,一旦确定端点开闭情况,整个代码中都应保持一致。上面的代码搜索去间就是左闭右开,即搜索区间包括左端点而不含右端点。有了此等认知基础,我们可以进行接下来的讨论。

思考题1:

left, right = 0, len(nums)#思考1:为什么这里是len(nums)而不是len(nums)-1

**解答:**因为是左闭右开区间,所以搜索区间不包含右端点。如果写为len(nums) - 1则搜索不到列表最后一个元素。

思考题2:

mid = left + (right - left) // 2#思考2:为什么这里写成此种格式而非更简洁的mid = (left + right) // 2

**解答:**如果该列表容量巨大,则left + right运算后可能会出现溢出风险

思考题3:

while left < right:#思考3:这里为什么是严格小于而非小于等于

**解答:**因为是左闭右开区间,因而一个开区间端点与一个闭区间端点永远无法相等,因而写等号纯属做无用功。

  • 如果写了等号会导致什么错误?
    写了等号就会导致当left = right时会继续执行一次循环

思考题4:

while left < right:
		if nums[mid] > target:
			right = mid 
		elif nums[mid] < target:
			left = mid + 1#思考4:为什么上面right不需要+1而left需要+1
		else:
			return mid
	return -1
	'''解答:
	主要的作用在于避免重复搜索
	if nums[mid] > target:说明目标值在left~mid中,因为本来mid就不等于target,自然可以将它当右端点,因为右端点是开区间,不会有重复搜索【left,mid)
	elif nums[mid] < target:说明目标值在mid~right中,因为本来mid就不等于target,自然可以将它当左端点,但因为左端点是闭区间,因而可以将左端点写为mid+1,避免重复搜索mid【mid+1,right)
	'''
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值