目录
0、二分法简介
1、二分入门-洛谷P1024一元三次方程求解
2、Java快速输入+二分查找 P2249查找
3、二分查找- 洛谷P1678 烦恼的高考志愿
4、二分答案+java快速输入 洛谷P1873 砍树
二分查找(英语:binary search),也称折半搜索(英语:half-interval search)、对数搜索(英语:logarithmic search),是用来在一个有序数组中查找某一元素的算法。
以在一个升序数组中查找一个数为例。
它每次考察数组当前部分的中间元素,如果中间元素刚好是要找的,就结束搜索过程;如果中间元素小于所查找的值,那么左侧的只会更小,不会有所查找的元素,只需到右侧查找;如果中间元素大于所查找的值同理,只需到左侧查找。
时间复杂度
二分查找的最优时间复杂度为O(1) 。
二分查找的平均时间复杂度和最坏时间复杂度均为 O(logn)。因为在二分搜索过程中,算法每次都把查询的区间减半,所以对于一个长度为n 的数组,至多会进行 O(logn) 次查找。
空间复杂度
迭代版本的二分查找的空间复杂度为O(1) 。
递归(无尾调用消除)版本的二分查找的空间复杂度为O(logn) 。
二分查找是一种在有序数组中查找某一特定元素的查找算法。
查找过程从数组的中间元素开始:如果中间元素正好是要查找的元素,则查找过程结束;
如果某一特定元素大于或者小于中间元素,则在数组大于或小于中间元素的那一半中查找,而且跟开始一样从中间元素开始比较。
如果在某一步骤数组为空,则代表找不到。
「连续」「单调」「确切答案」 解通常是唯一的,或者不存在。
数组a二分查找某元素的模板:
static int find(int x) {
int l=1,r=n;
while(l
二分答案,即通过题目中包含的单调性对答案进行二分。大多数二分答案可以看做是标准二分法套了一个奇奇怪怪的函数。 解答需要使用二分答案的题目,最重要的是观察出单调性。
通常来说,二分答案题目为下列两种中的一种:给定一个评价函数,求评价函数的最小值 / 最大值 。给定一个条件,要求在满足条件的同时,使得代价最小。计算函数或者判断符合条件需要消耗极长的时间;或者评价函数的值域太大了,不能一 一计算。
oj:https://www.luogu.com.cn/problem/P1024 标签:数论,数学,二分答案,枚举,暴力,分治,NOIp提高组2001(或之前)
package 二分查找与二分答案;
import java.util.Scanner;
public class P1024一元三次方程求解 {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
double a=in.nextDouble();
double b=in.nextDouble();
double c=in.nextDouble();
double d=in.nextDouble();
double y1,y2,j;
for(double i=-100;i<=100;i+=0.001) {
j=i+0.001; //j取到保留的小数位下一位
y1=a*i*i*i+b*i*i+c*i+d;
y2=a*j*j*j+b*j*j+c*j+d;
if(y1*y2<=0)//y1,y2异号或其一为0
System.out.printf("%.2f ",(i+j)/2);
}
}
}
oj:https://www.luogu.com.cn/problem/P2249 标签:二分答案
package 二分查找与二分答案;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StreamTokenizer;
public class P2249查找 {
static int[] a;
static int n;
public static void main(String[] args) throws IOException {
StreamTokenizer in = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
PrintWriter out=new PrintWriter(new OutputStreamWriter(System.out));
in.nextToken();
n=(int)in.nval;//相当于int n = in.nextInt();
in.nextToken();
int m=(int)in.nval;
a=new int [n+1];
int[] b=new int [m+1];
a[0]=-1;//有可能会要查找等于0的数,所以我们把第一个改成-1
for(int i=1;i<=n;i++) {
in.nextToken();
a[i]=(int)in.nval;
}
for(int i=1;i<=m;i++) {
in.nextToken();
b[i]=(int)in.nval;
out.print(find(b[i])+" ");
}
out.flush();
}
static int find(int x) {//参数的数目直接影响调用函数的速度,参数越多,调用函数就越慢.这题如果函数是两个参数,就会超时。
int l=1,r=n;
while(l=x)r=mid;// 如果中间值大于等于目标值就继续往左边找
else l=mid+1;
}
if(a[l]==x)return l;
else return -1;
}
}
java快速输入输出用法见:https://blog.csdn.net/qq_44491991/article/details/115186693
OJ:https://www.luogu.com.cn/problem/P1678 标签:模拟,贪心,排序,二分查找,高性能
package 二分查找与二分答案;
import java.util.Arrays;
import java.util.Scanner;
public class P1678烦恼的高考志愿 {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int m=in.nextInt();
int n=in.nextInt();
int[] a=new int[m];
int[] b=new int[n];
for(int i=0;i=a[mid])l=mid;
else r=mid;
}
ans+=Math.min(Math.abs(a[l]-b[i]),Math.abs(a[r]-b[i]));//加上两个绝对值中最小
}
System.out.println(ans);
}
}
oj:https://www.luogu.com.cn/problem/P1873 标签:二分答案,高性能
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StreamTokenizer;
public class Main {
public static void main(String[] args) throws IOException {
StreamTokenizer in = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
in.nextToken();
int n=(int)in.nval;
in.nextToken();
int m=(int)in.nval;
int[] a=new int[n];
int l=0,r=0;
for(int i=0;ix)sum+=a[i]-x;
// }
// return sum>=m;
int sum = 0;
for(int i = 0;i < a.length;i++) {
if(a[i] > x) {
sum += (a[i] - x);
if(sum >= m)return true;//只要满足需求即可返回了!防止sum超范围。
}
}
return false;
}
}
未完待续。。。