既然你已经知道了应该如何来实现递归函数,现在就可以回过头再去看看我们的二分搜索了。回忆一下,这个算法的基本思想是查看中间值,然后通过递归来搜索列表的下半部分或上半部分。
递归的基本情况
是我们可以停止递归的条件,也就是找到目标值
或者是找不到地方的时候。递归调用每次都会将问题的大小减半
。因此,我们需要为每个递归调用都指定一下列表中仍然需要被“执行”的位置的范围。我们可以通过这样的方式来实现:把低索引(low)和高索引(high)作为参数与列表一起进行传递。然后保证在每次调用的时候,都只在列表的低索引和高索引之间进行搜索
def recBinSearch(x, nums, low, high):
if low > high:
return -1
mid = (low + high) / 2
item = nums[mid]
if item == x:
return mid
elif x < item:
return recBinSearch(x, nums, low, mid - 1)
else:
return recBinSearch(x, nums, mid + 1, high)
然后,我们可以使用对递归二分搜索的适当调用来实现我们最初的搜索功能。也就是告诉它,在一开始的时候,对列表的0~len(nums) - 1的元素进行搜索:
def recBinSearch(x, nums, low, high):
if low > high:
return -1
mid = (low + high) //2
item = nums[mid]
if item == x:
return mid
elif x < item:
return recBinSearch(x, nums, low, mid - 1)
else:
return recBinSearch(x, nums, mid + 1, high)
def search(items, target): # items 列表 target 待查询的值
return recBinSearch(target, items, 0, len(items) - 1)
print(search([1,2,3,4,6],4)) #3
当然,我们最初的循环版本可能会比这个递归版本要快一点,这是因为调用函数通常会比迭代循环要慢一些。然而,递归版本的二分搜索算法,能够让它分而治之的结构更加明显。
总结
- 二分查找的
基本情况
就是找到了 - 如何缩小问题规模? 查找范围在缩小