您的位置:首页 > 其它

二分查找的思考

2015-01-05 20:44 155 查看
推荐一篇不错的文章: 二分查找之美

二分查找

二分查找的代码是这样

int binarySearch(int* A, int n, int target){
int l = 0;
int r = n-1;
while(l<=r){
int mid = (l+r)>>1;
if(A[mid]==target) return mid;

if(A[mid]<target) l=mid+1;
else r=mid-1;
}
return -1;
}

循环不变式:

如果key存在于原始数组[0,n-1],那么它一定在[left,right]中。

初始化:

第一轮循环开始之前,处理的数组就是原始数组,这时显然成立。

保持:

每次循环开始前,key存在于待处理数组array[left, ..., right]中。

对于array[mid]<key,array[left, ..., mid]均小于key,key只可能存在于array[mid+1, ..., right]中;

对于array[mid]>key,array[mid, ..., right]均大于key,key只可能存在于array[left, ..., mid-1]中;

对于array[mid]==key,查找到了key对应的下标,直接返回。

在前两种情况中,数组长度每次至少减少1(实际减少的长度分别是mid-left+1和right-mid+1),直到由1(left==right)变为0(left>right),不会发生死循环。

终止:

结束时,left>right,待处理数组为空,表示key不存在于所有步骤的待处理数组,再结合每一步排除的部分数组中也不可能有key,因此key不存在于原数组。

二分查找左边界和右边界

其实就是leetcode的 Search for a range

我是这么写的

class Solution {
public:
vector<int> searchRange(int A[], int n, int target) {
//不如叫:二分查找左右断点
vector<int> range = {-1,-1};
int l=0;
int r=n-1;
int mid;
while(l<=r){
mid=(l+r)/2;
if(target<=A[mid]) r=mid-1;
else l=mid+1;
}
if(A[l]==target) range[0] = l;

l=0;
r=n-1;
while(l<=r){
mid=(l+r)/2;
if(target<A[mid]) r=mid-1;
else l=mid+1;
}
if(A[r]==target) range[1] = r;
return range;
}
};

问题是,为什么这样查找左边界的时候,跳出循环时, l就是要找的第一个元素的下标?

循环不变量:

如果 存在, [l,r+1]包含

最后退出循环的时候是不是有 l=r+1, 会不会是 l=r+2 ?
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: