二分需要注意的三个点:
- 循环退出条件
(区间只剩一个数)
- mid的取值
(防止爆int)
- l和r的更新
(关键是取左取右)
import java.util.Scanner;
public class Main{
static int N = 100010;
static int a[] = new int[N];
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
int m = scanner.nextInt();
for(int i = 1; i <= n; i++) a[i] = scanner.nextInt();
while(m-->0) {
int x = scanner.nextInt();
int l = findL(x,n)-1;
int r = findR(x,n)-1;
System.out.println(l+" "+r);
}
}
private static int findR(int x,int n) {
int l = 1,r = n;
while(l<r) {
int mid = l+1+((r-l)>>1);
if(a[mid]<=x) l = mid;
else r = mid-1;
}
return a[l]==x?l:0;
}
private static int findL(int x,int n) {
int l = 1,r = n;
while(l<r) {
int mid = l+((r-l)>>1);
if(a[mid]>=x) r = mid;
else l = mid+1;
}
return a[l]==x?l:0;
}
}
另一种更容易理解的写法
查询第一个值为value的元素下标
如果 mid 等于 0,那这个元素已经是数组的第一个元素,那它肯定是我们要找的;如果 mid 不等于 0,但 a[mid]的前一个元素 a[mid-1]不等于value,那也说明a[mid]就是我们要找的第一个值等于给定值的元素。
如果经过检查之后发现 a[mid]前面的一个元素 a[mid-1]也等于 value,那说明此时的 a[mid]肯定不是我们要查找的第一个值等于给定值的元素。那我们就更新 high=mid-1,因为要找的元素肯定出现在[low, mid-1]之间。
public int bsearch(int[] a, int n, int value) {
int low = 0;
int high = n - 1;
while (low <= high) {
int mid = low + ((high - low) >> 1);
if (a[mid] > value) {
high = mid - 1;
} else if (a[mid] < value) {
low = mid + 1;
} else {
if ((mid == 0) || (a[mid - 1] != value)) return mid;//重点是这一行!!!
else high = mid - 1;
}
}
return -1;
}
查找最后一个值为给定值的元素下标
public int bsearch(int[] a, int n, int value) {
int low = 0;
int high = n - 1;
while (low <= high) {
int mid = low + ((high - low) >> 1);
if (a[mid] > value) {
high = mid - 1;
} else if (a[mid] < value) {
low = mid + 1;
} else {
if ((mid == n - 1) || (a[mid + 1] != value)) return mid;
else low = mid + 1;
}
}
return -1;
}
查找第一个大于等于给定值的元素下标
public int bsearch(int[] a, int n, int value) {
int low = 0;
int high = n - 1;
while (low <= high) {
int mid = low + ((high - low) >> 1);
if (a[mid] >= value) {
if ((mid == 0) || (a[mid - 1] < value)) return mid;
else high = mid - 1;
} else {
low = mid + 1;
}
}
return -1;
}
查找最后一个小于等于给定值的元素下标
public int bsearch7(int[] a, int n, int value) {
int low = 0;
int high = n - 1;
while (low <= high) {
int mid = low + ((high - low) >> 1);
if (a[mid] > value) {
high = mid - 1;
} else {
if ((mid == n - 1) || (a[mid + 1] > value)) return mid;
else low = mid + 1;
}
}
return -1;
}