二进制搜索不变以查找元素的首次出现

invariant of binary search for finding first occurrence of an element

本文关键字:元素 查找 搜索 二进制      更新时间:2023-10-16

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

(

首先,我为自己设置了这个不变的。

我的不变

"始终是a [l]< = q,还有a [r]> q" ==>"始终l< = ind and> ind and> 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]将为&lt; = q

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

我已经看到了一些实现lower_bound的代码,该if(a[mid]==q)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[l,r)的范围内(,但在第5行中考虑if(q==a[mid]),然后显然是因为它违反了([l,r],因为CC_16是相等的,并且可以是第一次出现(。

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

假设我们有一个序列

..., <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

一些可能有用的引用:

  • col.4:编写正确的程序&ndash;J.Bentley。编程珍珠。Addison-Wesley,2 nd Ed。,1999。书网站

  • J.Bentley。编程珍珠:编写正确的程序。ACM 26 ,1040(1983(的通信。全文

  • 二进制搜索&ndash;DR.DOBB的日记第一部分,第二部分,第三部分,第四部分,第五部分第六部分,第七部分,第七部分,第IX部分,X部分