一、主要步骤:
1.对数组等进行排序,保证查找的序列是有序的
2.进行二分查找
1.二分概念:
二分算法又称折半查找,即在一个单调有序的集合中查找一个解。每次分为左右两部分,判断解在哪个部分中并调整上下界,直到找到目标元素,每次二分后都将舍弃一半的查找空间。
2.算法复杂度
O(logn)
3.二分法常见模型
(1)二分查找
在一个单调有序的区间上求解分界点。
(2)二分答案
最小值最大(最大值最小)问题,这类双最值问题常常选用二分法求解,也就是确定答案后,配合贪心、DP等其他算法检验这个答案是否合理,将最优化问题转换为判定性问题。
注:一般题目默认在一个从小到大的区间上。
二、为什么要用二分:
二分查找法,又称折半查找法。但该方法是建立在有序的前提下的,基本思路就是:先找到那个有序序列的中间元素mid,然后拿它和要找的元素K进行比较,就可以初步判断K所在范围,既然查找范围已确定,自然该范围之外的元素就可以不用再查找了(你看这样相较于顺序查找一下子就可以省略一半的元素不用查找了,这就是效率啊!!!)。当然接下来还会按照上面的步骤反复查找下去。
二分的时间复杂度是O(logn),比直接查找要快。
三、模板代码:
1.查找数组中是否存在n
#include<bits/stdc++.h>//万能头
using namespace std;
/*找是否存在数n*/
int a[10]={0,1,2,3,4,5,6,7,8,9};
int main(){
int n;
cin>>n;
int left=0,right=9,mid;
while (left <= right){
mid = (left + right) >>1;//计算中间元素的下标
if (a[mid] < n) left = mid + 1;
else if (a[mid] > n) right = mid - 1;
else break;
}
if (left > right) printf("没有找到该数\n");
else printf("找到了\n");
return 0;
}
2.查找n在数组中的范围
/*找n在数组中的范围(下标)*/
while(left<right-1){
mid=(left+right)>>1;
if(n>=a[mid])
left=mid;
else right=mid;
}
cout<<left<<" "<<right;
四、二分函数
1.binary_search()——利用二分方法判断一个数是否被找到
vector<int> a { 1,1,2,2,3,3 };
int aa=binary_search(a.begin(),a.end(),10);//bool
cout<<aa;//1能被找到,0不能被找到
2.lower_bound()——返回第一个大于等于搜索数的位置,要减去地址
3.upper_bound()——返回第一个大于搜索数的位置,要减去地址
vector<int> a { 1,1,2,2,3,3 };//对于一个已经排好序的数组
//插入一个数,那么应该在哪个位置
int aa=lower_bound( a.begin(),a.end(),3 )-a.begin();
int bb=upper_bound()(a.begin(),a.end(),3)-a.begin();
cout<<aa<<" "<<bb;
/*返回指针即下标
第一个位置是下标为aa的位置
最后一个位置是下标为bb的位置*/