二分算法最重要的就是边界问题,边界一定要确定好,并且自己也要清晰,要不然就会混乱。
什么时候用到二分呢?当涉及到快速筛选有序序列的时候就应该想到,其实二分也经常跟排序算法结合着一起使用
一个是确立左端点的
while(l < r) { // 确立左端点
int mid = l + r >> 1;
if(a[mid] >= x) r = mid;
else l = mid + 1;
}
想一想退出这个循环的时候是不是
l>=r
的时候,如果找到这个数的时候即l==r
的时候,l = mid + 1,即左端点不断地向右边靠近,所以这是确立左端点的同理右端点
确立右端点的
while(l < r) { // 确立右端点
int mid = l + r + 1>> 1;
if(a[mid] <= x) l = mid;
else r = mid - 1;
}
给定一个按照升序排列的长度为?n的整数数组,以及?q个查询。
对于每个查询,返回一个元素k的起始位置和终止位置(位置从?00?开始计数)。
如果数组中不存在该元素,则返回?-1 -1
。
第一行包含整数?n和?q,表示数组长度和询问个数。
第二行包含?n个整数(均在?1~100001~10000?范围内),表示完整数组。
接下来q行,每行包含一个整数?k,表示一个询问元素。
共q行,每行包含两个整数,表示所求元素的起始位置和终止位置。
如果数组中不存在该元素,则返回?-1 -1
。
1≤n≤1000001≤≤100000
1≤q≤100001≤≤10000
1≤k≤10000
代码:
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int n = in.nextInt();
int q = in.nextInt();
int[] a = new int[n];
for(int i =0 ;i < n;i ++) { // 这里千万不能从1开始,要不然答案会错
a[i] = in.nextInt();
}
while(q > 0) {
q--;
int x = in.nextInt();
int l = 0, r = n - 1;
while(l < r) { // 确立左端点
int mid = l + r >> 1;
if(a[mid] >= x) r = mid;
else l = mid + 1;
}
if(a[l] != x) {
System.out.println("-1 -1");
continue;
}
System.out.print(l + " ");
r = n - 1;
while(l < r) { // 确立右端点
int mid = l + r + 1>> 1; // 一定要注意这里有个+1
if(a[mid] <= x) l = mid;
else r = mid - 1;
}
System.out.println(l);
}
}
}
给定一个浮点数?n,求它的三次方根。
**
输入格式**
共一行,包含一个浮点数?n。
输出格式
共一行,包含一个浮点数,表示问题的解。
注意,结果保留?66?位小数。
数据范围
?10000≤n≤10000
输入样例:
1000.00
输出样例:
10.000000
代码:
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
double n = in.nextDouble();
double l = -1000,r = 1000;
while(r - l > 1e-8) {
double mid = (r + l) / 2;
if(mid * mid * mid >= n) {
r = mid;
} else {
l = mid;
}
}
System.out.printf("%.6f",l);
}
}