#二分查找 while循环版
def binarySearch(arr, target):
l = 0
r = len(arr) - 1
while(l <= r):
# 为什么这个=号的影响这么大呢?l < r就不行呢?
# 因为如果没有这个等号,当r和l指针重合时就进不来了。r和l重合,意味找到了,此时应该进入while把结果返回出去。
# r和l重合的下一次迭代就该返回-1了;
mid = (l+r)//2
if arr[mid] == target : return mid
if arr[mid] < target:
l = mid + 1
elif arr[mid] > target:
r = mid - 1
return -1
arr = [1,2,3,4,5,6,7,8,9,90,111]
target = 7.5
print("Index is {:d}".format(binarySearch(arr, target)))
容易犯错误的点:
手写二分查找的时候,经常会踩的坑:
自己蒙着头写了一遍,发现判断条件那块,总是写错。
while r<=l都应该进入循环!!!
为什么呢?因为如果没有这个等号,当r和l指针重合时就进不来了。r和l重合,意味找到了,此时应该进入while把结果返回出去。
当然还有迭代的写法,那么把l,r也都放到形式参数中去吧。
#二分查找 递归版本
a = [1,2,3,4,5,7,8,9,10]
target = 9
def binsearch(ilist, target, lp, rp):
if lp > rp : return -1
mid = (lp + rp) // 2
print("lp is {}, rp is {}, mid is {}".format(lp, rp,mid))
if ilist[mid] == target:
return mid
elif ilist[mid] < target:#如果ilist[mid] < target意味着,从mid+1开始比对是合理的;
return binsearch(ilist, target, mid+1, rp)
else:#如果ilist[mid] > target意味着,从0到mid-1开始比对是合理的;
return binsearch(ilist, target, lp, mid-1)
print(binsearch(a, target, lp=0, rp=len(a)))
1、为什么输出结果会是None;
答:递归时候,没有在函数前,return;
2、Process finished with exit code -1073741571 (0xC00000FD),(tar小于list的最小值,或者tar没在list中)
答:
情况1:递归的输入参数没有写好,忘记mid+1或者mid-1了;
情况2:递归的结束条件没有考虑周全,忘记lp一定要小于rp;
3、IndexError: list index out of range(tar大于list的最大值)
答:
情况1:递归的结束条件没有考虑周全,忘记lp一定要小于rp;
反过来理解二分查找:
1、如果忘记写return
1)会出现返回None的结果;
2、如果忘记更新左右指针呢?mid+1, mid-1
1)如果能找到tar,则没有报错;
2)如果tar没在list中,则会一直循环,永远也不停止,一直到爆栈;会出现lp和rp相等的局面;
3、如果忘记考虑递归的结束条件还有lp>rp呢?
1)会出现一直递归,爆栈的局面;
# 递归的解决方案 def binarySearch(arr, target, l ,r): if l <= r: mid = (l+r)//2 if arr[mid] == target : return mid if arr[mid] < target: l = mid + 1 return binarySearch(arr, target, l ,r) #这里总是忘记写return else: r = mid - 1 return binarySearch(arr, target, l ,r) else: return -1 arr = [1,2,3,4,5,6,7,8,9,90,111] l = 0 r = len(arr) - 1 target = 8 res = binarySearch(arr, target, l, r) print("Index is {:d}".format(res))
用递归的方法,解决这个问题时,总是忘记,return 递归函数的结果
-------------------------------------------
加分项,骚操作,不建议使用:
天啊!!!
我从来没有考虑过这个问题:
mid = low + (high-low) //2
--------------------------------------
二分查找,升级版本,如果有相同元素的话输出range