BinarySearch
查找前提
有序序列
查找元素
递归实现
代码
#include<stdio.h>
int BinarySearch(int a[], int left, int right, int x)
{
if(left > right) return -1;
/*避免溢出:int mid = left + (right - left)/2*/
int mid = (left+right)/2;
if(a[mid]==x) return mid;
else if (x < a[mid])
return BinarySearch(a, left, mid-1, x);
else if (x > a[mid])
return BinarySearch(a, mid+1, right, x);
}
非递归实现(更常用)
/*二分区间左闭右闭, 传入初值为[0, n-1]*/
#include<stdio.h>
int BinarySearch(int a[], int left, int right, int x)
{
int mid;
while(left <= right)
{
mid = (left + right)/2;
if(a[mid] == x) return mid;
else if(a[mid] > x) right = mid - 1;
else left = mid + 1;
}
return -1;
}
测试用例
int main()
{
int a[5] = {1,2,3,4,5};
int index = BinarySearch(a, 0, 4, 7);
printf("%d\n", index);
return 0;
}
拓展
求第一个大于等于x的元素的位置
代码实现
#include<stdio.h>
/*左闭右闭区间,传入初值为[0, n]*/
int lower_bound(int a[], int left, int right, int x)
{
int mid;
while(left < right)
{
mid = (left + right)/2;
if(a[mid] >= x) right = mid;
else left = mid + 1;
}
return left;
}
注意点
- x不一定是数组中的存在元素
- x可能插到数组末尾
返回一地个大于x的元素的位置
代码实现
#include<stdio.h>
/*左闭右闭区间,传入初值为[0, n]*/
int upper_bound(int a[], int left, int right, int x)
{
int mid;
while(left < right)
{
mid = (left + right)/2;
if(a[mid] > x) right = mid;
else left = mid + 1;
}
return left;
}
注意点
与上例只有一'='之差
总结
/*寻找有序序列,第一个满足某条件的元素*/
/*二分区间为[0,n]:必须涵盖所有解的取值*/
int BinarySearch(int a[], int left, int right, int x)
{
int mid;
while(left < right) /*left == right 意味找到唯一解*/
{
mid = (left+right)/2;
if(条件) right = mid; /*[left, mid]继续查找*/
else left = mid + 1; /*[mid + 1, right]继续查找*/
}
return left; /*返回夹出来的值*/
}
其他应用
求函数零点
快速幂
递归写法
求(a^b)%m
typedef Long Long LL;
LL binaryPow(int a, int b, int m)
{
if(b == 0) return 1;
if(b % 2 == 1) return a*binaryPow(a, b-1,m)%m;
else
{
LL n = binaryPow(a, b/2, m);
return n*n%m;
}
}