对于任意给定的实数数组,可以排序(从小到大排列)并实现任意目标的查找,若目标不在数组中,则返回其加入数组但不改变排序的索引值。
新手一枚,不足之处,敬请赞之→ _ →
解题思路
1.简单说二分查找就是一个切片查找的过程,通过对比目标(t)和中点值(m)[0]的大小决定是下一级查找是向左还是向右。例如:原数组[a,b, …, m-1,m,m+1,c,…,d],若t>m,则在1级数组[m+1,c, … ,d]中继续找中点,比大小,定左右,如此递归(为加快搜索进度,这里舍弃了中点值)。
[0]:中点值(m)的索引通过数组的端点(left和right)的索引和/2取整获得:
m=int((left+right)/2)
2.一般可以定位目标的切片长度(l)为1或2:
l=1,的上级切片长度为3,形如:[a,b,c],此时m=b,对比t和b的大小,切片即剩下[a]或[b];
l=2,的切片形如:[a,b],此时m=a,此时t可以在3个位置,若t<a,下级切片长度即为-1,此时有:
left=a(的索引),right=m-1=a-1
而此时t已经定位,t(的索引)=m(的索引)
若a<t<b,则t>a=m, left=m+1=b=right, 下级切片长度为1,t=m
若t>b,则t>a=m,left=m+1=b=right,下级切片长度为1,t=m+1。
3.综上,结束递归的条件可以分为3类:
1、t=m,返回中点索引;
2、切片长度为±1,通过比较t和m,返回中点索引或中点索引+1;
3、递归出错,返回None(因为当切片长度为-1时,L=R+1=m+1,若递归继续将进入死循环)。
由于切片操作会改变原数组,所以文章通过改变端点索引来定位中点索引,并且将中点索引对应的值命名为中点值[1]。
程序
def binary_search(thelist, target, right, left=0):
'''binary search'''
mid_index = int((left + right)/2)
mid_value = thelist[mid_index]
if left >= right:
if target > mid_value:
return mid_index+1
else:
return mid_index
if target == mid_value:
return mid_index
elif target < mid_value:
return binary_search(thelist, target, right=mid_index-1)
else:
return binary_search(thelist, target, right, left=mid_index+1)
说明
(1)查找需要列表顺序排列,并初始化列表右端索引,如:
nums= [5, 6, 8, 90, 7, 1, 86, 31, 6, 9]
target = 80
nums.sort()
right = len(nums) - 1
result = binary_search(nums,target,right)
(2)递归错误的条件设置待定。
(3)若列表中有重复元素,返回内容待定。
上述问题已在2.0版中解决,详见:link1.
参考资料及问题来源:
[1] 本文方法参考了知乎《二分法查找的递归实现(python)》
链接:link2.
问题来源于贪心学院的“递归查找”一节。