二分搜索:从有序数组中查找某个值、假设一个解并判断是否可行、最大化平均值

88 篇文章 1 订阅

从有序数组中查找某个值

Lower_bound

在这里插入图片描述
在这里插入图片描述

package 二分搜索;

import java.util.Scanner;

public class 有序数据中查找某个值LOWERBOUND {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner sc=new Scanner(System.in);
		int n=sc.nextInt();
		int[] a=new int[n];
		for(int i=0;i<n;i++){
			a[i]=sc.nextInt();
		}
		int k=sc.nextInt();
		
		//初始化解的存在范围
		int lb=-1;
		int ub=n;
		//重复循环,知道解的存在范围不大于1
		while(ub-lb>1){
			int mid=(lb+ub)/2;
			if(a[mid]>=k){
				//如果mid满足条件,则解的存在范围变为(1b,mid)
				ub=mid;
			}else{
				//如果不满足条件(mid,ub)
				lb=mid;
			}
		}
		//此时lb+1=ub
		System.out.println(ub);
		
	}

}

假设一个解并判断是否可行

Cable master

在这里插入图片描述
在这里插入图片描述
二分搜索的模型试图解决这个问题
令:
在这里插入图片描述
求满足C(X)条件的最大值X,在区间初始化时,只需要使用充分大的数INF(>MAX)作为上界即可
lb=0;
ub=INF
现在的问题就是是否可以高效的判断C(X),由于长度LI的绳最多可以切除floor(Li,x)段长度位x绳子,因此
在这里插入图片描述
它可以在O(N)的时间内被判断出来
在这里插入图片描述

package 二分搜索;

import java.util.Scanner;

public class Cablemaster {

	private static int n;
	private static double[] a;
	private static int k;
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner sc=new Scanner(System.in);
		n = sc.nextInt();
		k = sc.nextInt();
		a = new double[n];
		for(int i=0;i<n;i++){
			a[i]=sc.nextDouble();
		}
		
		//初始化解的范围
		double lb=0,ub=Integer.MAX_VALUE;
		
		//重复循环,知道解的范围足够小
		for(int i=0;i<100;i++){
			double mid=(lb+ub)/2;
			if(C(mid))
				lb=mid;
			else
				ub=mid;
		}
		System.out.printf("%.2f",ub);
	}
	//判断是否满足条件
	private static boolean C(double x) {
		// TODO Auto-generated method stub
		int num=0;
		for(int i=0;i<n;i++){
			num+=(int)(a[i]/x);
		}
		return num>=k;
	}

}

如果在求解最大化或最小化问题中,能够比较简单地判断条件是否满足,那么使用二分搜索法就可以很好的解决问题

专栏,二分搜索的结束判定

在输出小数的问题中,一般都会制定允许的误差范围或是制定输出小数点后面的位数。因此在使用二分搜索法时,有必要设置合理的结束条件来满足精度的要求。在上面的程序中,我们指定了循环次数作为终止条件。1次循环可以把区间的范围缩小一半,100次的循环则可以达到10-30的精度范围,基本上是没有问题的。除此之外,也可以把终止条件设为像(ub-lb)>EPS这样,指定一个区间的大小。在这种情况下,如果EPS取得太小了,就有可会因为浮点小数精度的与您导致陷入死循环,请千万小心

最大化最小化

Aggressive cows

在这里插入图片描述
类似的最大化最小值或者最小化最大值的问题,通常用二分搜索法就可以很好的解决。
在这里插入图片描述
在这里插入图片描述

package 二分搜索;

import java.util.Arrays;
import java.util.Scanner;

public class 最大化最小值 {

	private static int n;
	private static int m;
	private static int[] x;

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner sc=new Scanner(System.in);
		n = sc.nextInt();
		m = sc.nextInt();
		x = new int[n];
		for(int i=0;i<n;i++)
			x[i]=sc.nextInt();
		
		//最开始时对x数组排序
		Arrays.sort(x);
		
		//初始化解的存在范围
		int lb=0,ub=Integer.MAX_VALUE;
		
		while(ub-lb>1){
			int mid=(lb+ub)/2;
			if(C(mid))
				lb=mid;
			else
				ub=mid;
		}
	}

	private static boolean C(int d) {
		// TODO Auto-generated method stub
		int last=0;
		for(int i=1;i<m;i++){
			int crt=last+1;
			while(crt<n&&x[crt]-x[last]<d)
				crt++;
			if(crt==n)
				return false;
			last=crt;
		}
		return true;
	}

}

最大化平均值

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

package 二分搜索;

import java.util.Arrays;
import java.util.Scanner;

public class 最大化最小值 {

	private static int n;
	private static int m;
	private static int[] x;

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner sc=new Scanner(System.in);
		n = sc.nextInt();
		m = sc.nextInt();
		x = new int[n];
		for(int i=0;i<n;i++)
			x[i]=sc.nextInt();
		
		//最开始时对x数组排序
		Arrays.sort(x);
		
		//初始化解的存在范围
		int lb=0,ub=Integer.MAX_VALUE;
		
		while(ub-lb>1){
			int mid=(lb+ub)/2;
			if(C(mid))
				lb=mid;
			else
				ub=mid;
		}
	}

	private static boolean C(int d) {
		// TODO Auto-generated method stub
		int last=0;
		for(int i=1;i<m;i++){
			int crt=last+1;
			while(crt<n&&x[crt]-x[last]<d)
				crt++;
			if(crt==n)
				return false;
			last=crt;
		}
		return true;
	}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

向上Claire

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值