我试图用二等分算法搜索发现的索引
def bi_search(nums: List[int], find: int) -> int:
"""
Return the index of the find
"""
if len(nums) == 0:
return -1
else:
mid = len(nums) // 2 #testEntry
if find == nums[mid]:
return mid
if find < nums[mid]:
sub_nums = nums[:mid]
return bi_search(sub_nums, find)
if find > nums[mid]:
sub_nums = nums[mid:]
return bi_search(sub_nums, find) #recursive case.
但是它不能按预期工作
In [26]: bi_search(list(range(1000)), 777)
Out[26]: 4
它返回基本情况的中点。
我注意到可以使用bisect — Array bisection algorithm — Python 3.7.3rc1 documentation
中的迭代方法来检索正确的索引是否可以在递归解决方案中获得正确的索引?
答案 0 :(得分:1)
如果在函数中添加print()
语句并使用一个较小的示例,则会看到问题:
def bi_search(nums, find):
print((nums, find))
...
print(bi_search(list(range(10)), 7))
输出:
([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], 7) # Looks good.
([5, 6, 7, 8, 9], 7) # Also good.
2 # Doh!
问题是您要返回的是最后检查的列表中的索引,而不是初始列表的索引。为了使您的方法可行,您需要通过递归调用传递更多信息-这很棘手。
另一种方法是传递每个呼叫的完整列表,然后随即调整搜索上下限。这还具有避免每次调用都创建新列表的优点。例如:
def bi_search(nums, find, i = None, j = None):
# Setup.
N = len(nums)
if i is None:
i = 0
j = N - 1
# Base case for failure.
if j < i:
return None
# Success or recurse.
mid = (i + j) // 2
if find == nums[mid]:
return mid
elif find < nums[mid]:
return bi_search(nums, find, i, mid - 1)
else:
return bi_search(nums, find, mid + 1, j)