文章目录
前言
希望可以帮助大家快速简单的了解和入门二分。
一、二分查找是什么?
概念:二分查找(Binary Search),也称为折半查找或对数搜索,是一种在有序数组中查找特定元素的高效算法。其基本原理是通过不断将搜索区间缩小一半来快速定位目标元素的位置。
具体来说,二分查找首先确定搜索范围的起始位置和结束位置,然后找到这个范围中间的元素与目标值进行比较。如果中间元素正好是要查找的元素,则查找成功;如果中间元素大于目标值,则在左半部分继续查找;如果中间元素小于目标值,则在右半部分继续查找。这种分而治之的思想使得每次比较后都能排除掉一半的数据,从而大大提高了查找效率,时间复杂度为O(log n)。
说人话:把答案所在的区间逐渐缩小,直到区间内只有答案。
编辑
二、模版
1.基础模版
1.先设立一个条件使数组可以一分为二
2.查找分左右查找:向左查找r=mid l=mid+1 向右查找l=mid r=mid-1( 向右查找时mid取(r+l+1)/2 )
因为二分算法有边界性问题,所以推荐大家背下模版,下面以一道题为例:
给定一个排好序的n个数,给出一个数k,查询k在n个数中的起始和终止位置,如果没有则输出"-1 -1"
#include<iostream>
#include<cstdio>
using namespace std;
const int N=1e6+10;
int p[N];//存下n个数的数组
int main()
{
int n,m;
scanf("%d%d",&n,&m);
for(int i=0;i<n;i++) scanf("%d",&p[i]);
while(m --)
{
int k;
scanf("%d",&k);
int l=0,r=n-1;//一般是要二分数组的范围
while(l<r)
{
int mid=(l+r)/2;//开始二分
if(p[mid]>=k) r=mid;//如果满足条件,说明小于等于mid的数中有答案,缩小r
else l=mid+1;//否则说明l-mid没有符合答案的数,扩大l为mid
}
if(p[l] != k) printf("-1 -1");//不存在这个数
else
{
printf("%d ",l);
//找k的终点位置
int l=0,r=n-1;
while(l<r)
{
int mid=(l+r+1)/2;//防止死循环
if(p[mid]<=k) l=mid;
else r=mid-1;
}
printf("%d",l);
}
printf("\n");
}
return 0;
}
2.注意点
- 数据必须是有序的:二分查找的前提条件是输入的数据必须是有序的。如果数据无序,需要先进行排序,这可能会影响整体的查找效率。
- 边界问题:在实现二分查找时,需要特别注意左右两端的边界问题。常见的写法有左闭右闭区间([0, nums.length-1])和左闭右开区间([0, nums.length))。选择其中一种后,会衍生出两种不同版本的二分查找写法。
- 单调性与二分法的关系:虽然题目具有单调性可以使用二分法,但二分法本身并不直接依赖于单调性。因此,在实际应用中,只要满足二分查找的基本要求即可。
3.经典例题
一.洛谷P1102A-B 数对
二.洛谷P2249 查找
总结
本文仅仅简单介绍了二分查找,二分查找是入门算法之一,也是常用的算法,希望这篇文章能帮到大家,也欢迎大家来CSDN看看