二分查找(英语:binary search),也称折半搜索(英语:half-interval search)、对数搜索(英语:logarithmic search),是用来在
时间复杂度
二分查找的最优时间复杂度为O(1) 。
二分查找的平均时间复杂度和最坏时间复杂度均为 O(logn)。因为在二分搜索过程中,算法每次都把查询的区间减半,所以对于一个长度为 n的数组,至多会进行 O(logn)次查找。
空间复杂度
迭代版本的二分查找的空间复杂度为 O(1)。
递归(无尾调用消除)版本的二分查找的空间复杂度为 O(logn)。
一个有序数组中查找某一元素的算法。
使用背景:
问题的解空间具有单调性:如果问题的解具有单调性,即满足某种特定的顺序或条件,那么通常可以使用二分法。例如,有序数组中查找某个元素、确定某个函数的最大值或最小值等。
解题的时候往往会考虑枚举答案然后检验枚举的值是否正确。若满足单调性,则满足使用二分法的条件。把这里的枚举换成二分,就变成了「二分答案」。
模板:
int l = 0,r = 10000000;
while(l+1<r)
{
int mid = (l+r)/2;
if(check(mid)) //check()函数是用来检查mid是否为可行解
r = mid;
else
l = mid;
}
//return r(最小值)
//return l(最大值)
例题: (来自洛谷)
解题思路:
首先我们要知道这个问题中的可行解是指“空旷指数”,也就是公路中的最大距离,接下来我们就应该去判断可行解的边界和单调性,边界很好知道,右边界是整条公路的长度,左边界是0。又因为对于任一给定的公路,假设为输入样例#1的情况,公路长度为101,我们可以知道在解空间(0,101)中,大于等于51的解均为可行解,而小于51的解均不可行,因为此时插一个路标不可能使空旷指数小于51,因为本题要求的是最小可行解,所以这个分界点51就是最优解。
我们可以知道在51左边的空旷指数,如果要满足,会需要比1更多的增设路标,而题目中提供了1个,因此我们将需要的增设路标当成y,空旷指数为x,这个函数是单调递减的,同时,我们根据题目给出的增设数量1,可以将解分为可行解和不可行解。
推广到更一般的情况,对于任意给定的公路长度L,路标N,最大增设K,我们可以知道
显而易见我们可以通过二分答案然后检验mid的值是否为可行解来不断二分最后求得最优解。
所以我们还需要一个check()函数来判断二分出来的值是不是可行解,那怎么判断对于一个空旷指数x它满不满足可行解的要求呢?我们知道,如果对道路增设count个路标之后,使得x比道路上每个相邻路标都大,如果添加的路标数小于提供的路标数,则x是可行解,反之,则不是。
代码:
arr = new int[N];
for (int i = 0; i < N; i++) {
arr[i] = s.nextInt();
}
int l = 0,r = arr[N-1]+1;
while(l+1<r)
{
int mid = (l+r)/2;
if(check(mid,M))
r = mid;
else
l = mid;
}
System.out.println(r);
static boolean check(int mid,int M)
{
int count = 0;
int sum = 0;
int cha = arr[0];
for (int i = 1 ; i < arr.length;) {
sum = arr[i]-cha;
if( sum > mid)
{
cha = cha + mid;
count++;
}
else {
cha = arr[i];
i++;
}
}
return count<=M;
}
注意:如果N=2,M=0,最优解为边界L,因此r应该取L+1。