上一篇必须掌握的算法之一 —— 递归算法
- 给定已按升序排列的n个元素A[0:n-1],现要在这n个元素中找出某一特定元素(查找关键字:key)
- 二分查找(Binary Search)又称为折半查找,是一种高效的算法。
- 二分查找要求待查找列表中的元素是有序的
设A[low…high]为当前查找区间,首先确定区间的中点位置mid=⌊(low +high)/2⌋;然后将待查的key值与A[mid]进行比较
- (1) 若key=A[mid],则查找成功并返回该元素的下标
- (2) 若key
- (3) 若key>A[mid],则查找右子表A[mid+1…high]
重复上述查找过程,直到找到关键字为key的元素或者查找区间为空为止
总共有n个元素,
渐渐跟下去就是n,n/2,n/4,…n/2^k(接下来操作元素的剩余个数),其中k就是循环的次数
由于你n/2^k取整后>=1
即令n/2^k=1
可得k=log2n,(是以2为底,n的对数)
所以时间复杂度可以表示T(n)=O(log2n)
#include
int binarySearch(int a[], int key, int n)
{
int low = 0;
int high = n - 1;
while (high >= low)
{
int mid = (low + high) / 2;
if (key == a[mid])
{
return mid;
}
else if (key > a[mid])
{
low= mid + 1;
}
else
{
high= mid - 1;
}
}
return -1;
}
int main()
{
int numbers[] ={2,4,7,10,11,45,50,59,60,66,69,70,79};
int key = 11;
int result = binarySearch(numbers, key,13);
printf("%d",result);
return 0;
}
#include
int binarySearch(int a[], int key, int low, int high)
{
if (low > high)
{
return -1;
}
int mid = (low + high) / 2;
if (key == a[mid])
{
return mid;
}
else if(key < a[mid])
{
return binarySearch(a, key, low, mid - 1);
}
else
{
return binarySearch(a, key, mid + 1, high);
}
}
int binarySearch(int a[], int key, int n)
{
int low = 0;
int high = n - 1;
return binarySearch(a, key, low, high);
}
int main()
{
int numbers[] ={2,4,7,10,11,45,50,59,60,66,69,70,79};
int key = 11;
int result = binarySearch(numbers, key, 13);
printf("%d",result);
return 0;
}
//求凸函数的最大值
while(Right-Left>=1e-6)
{
mid = (Left + Right) / 2
midmid = (mid + Right) / 2;
if(f(mid)>f(midmid))
Right = midmid;
else
Left = mid;
}
题目描述
使用
非递归
/递归
算法,实现二分搜索。
输入
多组数据输入,每组第一个数字为数组的长度n,然后输入n个整数,最后输入待查询的值。
输出
输出待查询值所在的位置,如果没有找到,则返回-1。
样例输入
3 1 2 3 2
4 0 1 3 4 2
样例输出
2
-1
#include
using namespace std;
int a[100];
int main()
{
int n,m;
while(~scanf("%d",&n))
{
for(int i=0;i<n;i++)
{
cin>>a[i];
}
scanf("%d",&m);
int left=a[0];
int right=a[n-1];
while (left<=right)
{
int x=(left+right)/2;
if(a[x]==m) {printf("%d\n",x+1);break;}
else if(a[x]>m)
{
right=x-1;
}
else
{
left=x+1;
}
}
if(left>right) printf("-1\n");
}
return 0;
}
#include
using namespace std;
int a[100];
int fun(int a[],int left,int right,int m)
{
if(left<=right)
{
int x=(left+right)/2;
if(a[x]==m) return x;
else if(a[x]>m) return fun(a,left,x-1,m);
else return fun(a,x+1,right,m);
}
else return -2;
}
int main()
{
int n,m;
while(~scanf("%d",&n))
{
for(int i=0;i<n;i++)
{
cin>>a[i];
}
scanf("%d",&m);
printf("%d\n",fun(a,a[0],a[n-1],m)+1);
}
return 0;
}
题目描述
设a[0:n-1]是已排好序的数组。请改写二分搜索算法,使得当待搜索元素x不在数组中时,返回小于x的最大元素的位置i和大于x的最小元素的位置j;当待搜索元素x在数组中时,返回的i和j相同,均为x在数组中的位置
输入
多组数据输入,每组第一个数字为数组的长度n,然后输入n个整数,最后输入带查询的值x。
输出
输出小于x的最大元素的位置i和大于x的最小元素的位置j;当待搜索元素x在数组中时,返回的i和j相同,均为x在数组中的位置
样例输入
1 2 3 2
4 0 1 3 4 2
样例输出
2 2
2 3
AC代码
#include
using namespace std;
int a[100];
int main()
{
int n,m;
while(~scanf("%d",&n))
{
int d=-1;
for(int i=1;i<=n;i++)
{
cin>>a[i];
}
scanf("%d",&m);
int left=a[1];
int right=a[n];
int i,j;
while (left<=right)
{
int x=(left+right)/2;
if(a[x]==m) {d=x;break;}
else if(a[x]>m)
{
right=x-1;
}
else
{
left=x+1;
}
}
if(d==-1)
{
i=right;
j=left;
}
else
{
i=d;
j=d;
}
printf("%d %d\n",i,j);
}
return 0;
}
如有错误,恳请指正
最后,如果这篇文章对你有帮助,欢迎一键三连
下一篇 分治算法之快速排序。
要么努力,要么放弃