二分查找法在算法题的运用

二分查找法在算法题的运用

二分法主要作用是缩短查找时间

贪吃的小Q(2018腾讯秋招)

【题目描述】小Q的父母要出差N天,走之前给小Q留下了M块巧克力。小Q决定每天吃的巧克力数量不
少于前一天吃的一半,但是他又不想在父母回来之前的某一天没有巧克力吃,请问他第一天最多能吃多少 块巧克力.

对于这道题,第一印象是求 由等比数列和S 形成的不等式的解
这个不等式大致形式为 S <=M ,但是如何解不等式呢?

由于巧克力的数量是给定了的M,那么解总在 区间【0,M )之间的整数。
可以从1开始逐个找解,但是太慢。
二分法有个转换形式是查找区间中小于KEY的最小值,所以可以用二分法解不等式。

注意,用二分法的时候要注意边界问题(Left,right)

JAVA源码如下

import java.util.Scanner;

public class Kakulate {

	public static void main(String[] args) {
		int m,n;
		Scanner sc=new Scanner(System.in);
		n=sc.nextInt();//天
		m=sc.nextInt();//数量
		
		int res=0,mid=0;
		int left=1,right=m;
		while(left<=right) {//二分查找
			mid=(left+right+1)/2;
			res=sum(mid,n);
			if(res==m) {
				break;
			}
			else if(res>m) {
				right=mid-1;
			}
			else if(res<m) {
				left=mid-1;
			}
		}
		System.out.println(left);
		
	}
	static int sum(int s,int n) {//计算总共吃的巧克力数
		int su = 0;
		for(int i=0;i<n;i++) {
			su +=s;
			s=(s+1)/2;
		}
		return su;
	}
}

如果逐个找肯定超时,2分法能更快的找出解。二分法的时间复杂度为 O(log2 n)

跳柱子问题

字节跳动2019春招题,现在还没公布吧,具体名字还有内容记不清了,简单的说就是

有n个柱子,第i个柱子高度为H(i) ,一个机器人当前位置在0(无柱子),机器人当前能量为E,跳向柱子i,如果E>H(I),则机器人能量增加
E-H(I),否则机器人的能量减去H(I)-E,问一开始需要至少多少能量才能全部跳过去?

计算一下E,可以发现不管E大于还是小于H,都是E=2*E-H。不难看出是 求经过所有柱子后 始终满足E>=0的解。
故可以用二分法求解,再确定区间,如果能量为H的最大值M,那么所有小于M的柱子都会为机器人增加能量,一定能跳过。
区间应为 【0 ,H的最大值】

JAVA源码如下

import java.util.Scanner;

//<2s
public class Testzhijie3 {

	public static void main(String[] args) {
	
		Scanner sc = new Scanner(System.in);
		int n=sc.nextInt();
		
		int[] h=new int[n];
		
		for(int i=0;i<n;i++) {
			h[i]=sc.nextInt();
		}
		
		
		int max=0,l=0,r=0, mid=0;
		for(int i=0;i<n;i++) {
			if(h[i]>max) {
				max=h[i];
			}
		}
		r=max;
		while(l<=r) {
			mid=(l+r)/2;
			if(judge(mid,h)) {
				r=mid-1;
			}else {
				l=mid+1;
			}
		}
		System.out.println(right);

	}
	static boolean judge(int x,int[] a) {//判断是否满足条件
		for(int i=0;i<a.length;i++) {
			x=2*x-a[i];
			if(x<0)
				return false;
		}
		return true;
	}
	

}

总结

二分查找法的优点是减少查找时间,解不等式是因为可以较快的查找出解(在log2 n的时间内完成,较快),但是注意解题时要先确定区间。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值