算法实质:
假设目标值在闭区间 中,每次将区间长度缩小一半,当
时,我们就找到了目标值。
(题目可能无解,二分一定有解)
二分模板(两个)(不会出错、死循环...)
- 当我们将区间
划分成
和
时,其更新操作是
或
,此时
应该取
。
search_1(l, r){
while(l<r){
mid = l+r>>1;
if(check(mid)) r = mid; // check()判断mid是否满足性质
else l = mid+1;
}
}
- 当我们将区间
划分成
和
时,其更新操作是
或
,此时
应该取
。
search_2(l, r){
while(l<r){
mid = l+r+1>>1;
if(check(mid)) l = mid;
else r = mid-1;
}
}
ex:
给定一个按照升序排列的长度为 n 的整数数组,以及 1 个查询,返回该查询元素 k 的起始位置和终止位置(位置从 0 开始计数)。如果数组中不存在该元素,则返回
-1 -1
。
import java.io.*;
class Main{
static int N = 100010;
static int n;
static int[] a = new int[N];
public static void main(String[] args) throws IOException{
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
n = Integer.parseInt(in.readLine());
String[] str = in.readLine().split(" ");
int l=0, r = n-1;
# 寻找起始位置
while(l<r){
int x = l+r>>1;
if(a[x]>=k)
r = x;
else
l = x+1;
}
# 如果查询到最后的位置不等于该元素的值,输出-1,-1,否则else
if(a[l]!=k)
System.out.println("-1 -1");
else{
System.out.print(l+" ");
# 查询终止位置
l = 0;
r = n-1;
while(l<r){
int x = l+r+1>>1;
if(a[x]<=k)
l = x;
else
r = x-1;
}
System.out.println(l);
}
}
}