算法--二分查找的精妙之处

版权声明:转载请注明来源 https://blog.csdn.net/tangyuan_sibal/article/details/88361383

今天做腾讯的暑假实习编程题,其中有一道题目是这样子的:

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

作为菜鸡的我只能跑出百分之二十的测试用例。。。。。。。
然后就按常例跑去讨论区看大佬的解法,有一个大佬用了二分查找来做这道题,只能说自己是真的菜,。。。思路都不对,更不要说用到二分查找了,大佬的思路是

小Q第一天肯定至少吃一块的,不然的话你这巧克力一块就可以吃一辈子了。。。,当然小Q最多也只能吃M块,总的也就那些。所以我们可以这样子设计,我们假设小Q在第一天吃了mid块,然后再N天能吃多少,如果刚好吃到M,这样就是我们要的结果,而且关键的是,小Q每天吃的巧克力是原来的一半,说明这是一个递增的数组,就是你mid越大,你能吃到的就越多是吧。所以我们在这个递增数组里面找到等于M的,这个时候就是查找的事情了,就可以用二分查找了

import java.util.Scanner;

public class Eating {

	public static void main(String[] args) {
		Scanner scanner = new Scanner(System.in);
		while(scanner.hasNext())
		{
			int n = scanner.nextInt();
			int m = scanner.nextInt();
			int res = fun(n,m);
			System.out.println(res);
		}
	}
	//对这些可能吃的情况,用二分查找进行查找到正确值
	public static int fun(int n,int m){
		//如果只有出去一天,则直接返回m
		if(n==1)
			return m;
		//每天吃的蛋糕数最少为1个,最多
		int low = 1;
		int high = m;
		while(low<=high)
		{
			int mid = (low+high+1)>>1;//向上取整,用移位运算比计算的好
			if(sum(mid,n)==m)return mid;
			else if(sum(mid,n)<m)
				low = mid;
			else
				high = mid;
		}
		return high;
	}
	//每天吃mid块,n天可以吃多少块
	private static int sum(int mid,int n) {
		int count = 0;
		for(int i=0;i<n;i++)
		{
			count += mid;
			mid = (mid+1)>>1;
		}
		return count;
	}
}

猜你喜欢

转载自blog.csdn.net/tangyuan_sibal/article/details/88361383