对于任意给定的实数数组,可以排序(从小到大排列)并实现任意实数(
target
)的查找,若t不在数组中,则返回其加入数组但不改变排序的索引值。
新手一枚,不足之处,敬请指点。
解题思路
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
left=a(的索引),right=m-1=a-1
而此时t已经定位,t(的索引)=m(的索引)
若aa=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, left = 0, right = -1):
thelist.sort()
right = thelist.index(thelist[right])
midindex = int((left + right)/2)
midvalue = thelist[midindex]
if target == midvalue:
return midindex
elif left >= right:
if target > midvalue:
return midindex+1
return midindex
elif target < midvalue:
return binary_search(thelist, target, left, midindex-1)
else:
return binary_search(thelist, target, midindex+1, right)
待续
(1)排序应该和查找分离。排序只需一次,而查找需要递归或循环,所以应该先对数组进行排序再查找;
(2)递归错误的条件该如何设置。
(3)舍弃中点值而出现了负长度的过度查找。保留中点的效率是高是低,亦或有更好的方法。
参考资料及问题来源:
[1] 本文方法参考了知乎《二分法查找的递归实现(python)》
链接:
link
.
问题来源于贪心学院的“递归查找”一节。