二进制搜索Python为什么我们使用mid + 1或mid-1

时间:2017-11-13 03:23:37

标签: python data-structures binary-search

我正在学习二进制搜索,示例代码使用“low = mid +1 and high = mid -1”,但我不明白为什么我们不使用“low = mid and high = mid”代替?

def binarysearch(sequence, value):
    lo, hi = 0, len(sequence) - 1
    while lo <= hi:
        mid = (lo + hi) // 2
        if sequence[mid] < value:
            lo = mid + 1
        elif value < sequence[mid]:
            hi = mid - 1
        else:
            return mid
    return None

my_list = [1, 3, 5, 7, 9]
binarysearch(my_list, 3)

3 个答案:

答案 0 :(得分:1)

原因是避免重叠搜索;它将搜索范围的边界放在尚未检查的项目上。

例如:如果mid位于索引10,则下一个搜索左侧将查看索引9之前的值,右侧搜索索引11处的值。

                    mid
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
|                 |    |                           |
<-from 0 to mid-1->    <-- from mid+1 to the end --> 

note that in this example, the boundary values are included        

答案 1 :(得分:0)

请让我试着解释为什么二进制搜索有效。假设我们有以下序列A=[-5, 10, 14, 33, 42, 42, 42]searched_value = 14

Iteration 1,     lo = 0, hi = 6, mid = 3     A[mid] > 14
Iteration 2,     lo = 0, hi = 2, mid = 1     A[mid] < 14
Iteration 3,     lo = 2, hi = 2, mid = 2     A[mid] = 14  (found!)

在算法的每次迭代中,我们可以得出结论:lohi总是包含搜索值的位置,我们将通过归纳证明迭代次数:

归纳假设:如果搜索到的值出现在序列中,它将始终包含在lohi之间。

基本案例:在迭代1 lo = 0hi = n-1包含所有元素,因此如果搜索到的值出现在序列中,它将包含在{{lo之间1}}和hi,并且不变量非常正确。

归纳步骤:如果搜索到的值包含在lohi之间的任何步骤中,它将继续包含在lohi之间{1}}在下一次迭代中。我们有3种可能性(这是问题的答案):

  • 如果A[mid] = searched_value:在这种情况下,算法会正确报告搜索值在序列中的位置,并且不变量是正确的,因为搜索的值介于lohi之间。
  • 如果A[mid] < searched_value:知道它是一个排序的序列,A[lo...mid] < searched_value之间的所有元素(包括A[mid]),因此我们可以分配lo=mid+1(仅在在上一次迭代中,不变量仍然是正确的。
  • 如果A[mid] > searched_value:知道它是一个已排序的序列,A[mid...hi] > searched value(包括A[mid])之间的所有元素,因此我们可以协助hi=mid-1(仅在searched_value中安全搜索下半部分,并且在下一次迭代中,不变量仍然是正确的。

鉴于此,在每次迭代时,算法总是在较小的段上搜索  在序列中,终止条件得到保证,因为只有1个元素是mid+1或者它是不同的,并且在下一次迭代中,算法将报告序列中不存在这样的元素。

结果证明算法是正确的(以及我们使用mid-1it 'should do something', transactional: false do end )的原因。

答案 2 :(得分:0)

我认为代码不起作用,因为当数组大小为偶数时,您不会退出 while 循环当我们使 l 或 r 等于 mid(wrong),而不是 mid + 1 或mid -1(正确)

正如您在下面看到的,它陷入了无止境的循环

例如:

Binary Search
Array = [8, 9,   11, 13]; target = 10
         0  1    2   3 
         l  m        r   m = (0 + 3)/2 = 1.5 or 1, arr[m] < target (coz 9 < 10), make l = m, 
            l    m   r   m = (1+3)/2 = 2, arr[m] > target (coz 11 > 10), make r = m, 
            l(m) r       m = (1+2)/2 = 1.5 or 1, arr[m] < target (coz 9 < 10), make l = m
            l    r(m)    m = (1+3)/2 = 2, arr[m] > target (coz 11 > 10), make r = m.
            l(m) r       m = (1+2)/2 = 1.5 or 1, arr[m] < target (coz 9 < 10), make l = m
            l    r(m)    m = (1+3)/2 = 2, arr[m] > target (coz 11 > 10), make r = m.
            ...
            ...