二分查找:
前提:正序数列
例如:一个长度为n的正序数列,查找一个数 target是否在这个数列当中
(1)递归实现:
1-取数列正中间的数mid,
如果mid和x相等,则找到结果,查找成功 返回True
如果mid比x大,则x应该在mid的左侧,我们把mid左侧当作一个新的数列li
如果mid比x小,则x应该在mid的右侧,我们把mid右侧当作一个新的数列li
2-对于新的数列li 进行1的查找工作
3-一直重复上面查找,生成新的数列li为空的时候则 数列当中没有数x 返回False
(2)循环实现:
通过循环改变数组的start end mid位置处的索引,直到找到该元素。
时间复杂度:
最优O(1) 第一次取中间数mid 找到了 这种概率很低
最坏O(log n) 假设n个数的数列,每次把数列分成两半,n除以多少次2 等于1 呢? log n次
'''
Creat by HuangDandan
2018-08-24
dandanhuang@sjtu.edu.cn
'''
#递推法实现二分法查找
def dichotomyFind(a,target): #a数组,target查找的目标值
n = len(a)
mid = (n-1) >> 1
flag = False
if not a: #细节1:每次递推a列表都是新的参数,需要对列表a进行判断
return flag
if a[mid] == target:
flag = True
return flag #细节2:找到就立即返回,结束查找
elif a[mid] > target:
return dichotomyFind(a[:mid],target) #细节3 return & mid-1
else:
return dichotomyFind(a[mid+1:], target)
'''
#bug
if not a: #细节1:每次递推a列表都是新的参数,需要对列表a进行判断
return flag
if a[mid] == target:
flag = True
return flag
elif a[mid] > target:
dichotomyFind(a[:mid],target) #细节3 return
else:
dichotomyFind(a[mid+1:], target)
return flag
'''
#循环实现二分法查找,通过循环改变索引值
def dichotomyFind2(a,target):
start = 0
end = len(a)-1
flag = False #标记位
while start <= end:
mid = (start + end) >> 1
if a[mid] == target:
flag = True
return flag
elif a[mid] > target:
start, end = 0, mid-1
else:
start, end = mid+1, end
# 跳出循环说明没找到 返回标记位
return flag
if __name__ == "__main__":
Lst2 = [0, 1, 2, 3, 4, 6, 6]
print(dichotomyFind2(Lst2,-1))
温故:
因为思想相同,循环和递归的时间复杂度是一样的。二分法递归的实现,每次都要开新的列表,实际上空间复杂度会更大