二元搜索的不变性,用于查找元素的首次出现

时间:2019-05-24 08:28:43

标签: c++ algorithm binary-search invariants

我在定义查找二进制搜索的第一个元素的不变性时遇到问题。 (我有一个排序数组a,我想找到等于某个数字q的第一个元素,如果不存在则返回-1)

首先,我暂时设置此不变式。

我的不变性

  

“总是a [l] <= q以及a [r]> q” ==>“总是l <= ind以及> ind”。

根据我的不变式,我编写了以下代码:

int l=0,r=n;
while(l<r){
    int mid=(r+l)/2;
    if(a[mid]==q){
        r=mid+1;
    }
    else{
        if(a[mid]>q){
            r=mid;
        }else if(a[mid]<q) l=mid+1;
    }
}
return l;

但是有一个问题,if(a[mid]==q)然后我必须选择一个不违反我的不变式的r

如果我选择mid-1,则会违反它,因为a[r]将是<= q

我必须遍历索引,直到找到索引a[i]>q的索引I,然后将r设置为该索引。 (r = i)==>但是如果我这样做不是O(log n)

我已经看到一些实现lower_bound的代码,将if(a[mid]==q)的{​​{1}}设置为r,但是我认为它们违反了它们的不变性,但是它们的代码正确并返回正确的值。

喜欢此代码:

mid

首先,不变式就像我的不变式(1- int l = 0; 2- int r = n; // Not n - 1 3- while (l < r) { 4- int mid = (l + r) / 2; 5- if (q <= a[mid]) { 6- r = mid; 7- } else { 8- l = mid + 1; 9- } 10- } 11- return l; i的范围内,但在第5行中考虑[l,r)则显然违反了,因为其({{1 }},因为if(q==a[mid])相等,并且可能是第一个出现)。

我是对的还是我对不变性没有正确的理解概念?

1 个答案:

答案 0 :(得分:0)

假设我们有一个序列

..., <q, <q, <q, q, q, ..., q, q, >q, >q, >q, ...
                 ^ (*)

其中<q>q)代表任何元素< q> q)。我们想找到点(*)。

我们有两个指针left < right。我们如何使用它们来区分这一点?答案很简单:left应该指向最后一个<q元素,right应该指向第一个q元素:

..., <q, <q, <q, q, q, ..., q, q, >q, >q, >q, ...
                 ^ right
             ^ left

不变式为:*left < q*right >= q

您建议的不变式*left <= q*right > q对应于该序列中的最后一个元素:

..., <q, <q, <q, q, q, ..., q, q, >q, >q, >q, ...
                                  ^ right
                               ^ left

一些有用的参考文献: