【刷题笔记】--二分查找--P1873 EKO / 砍树

题目: 


思路: 

锯片的高度是处于这一排中最矮的树和最高的树之间的,所以我们可以想到先对这一排树先进行排序,然后让left指向这一排最矮的树的高度,right指向最高树的高度。进行二分查找。但对于这个情境,有两种情况,一种是找不到目标值,这个时候我们找刚好砍最少数目的高度,一种是找得到目标值。


代码: 

#include<stdio.h>
int cmp(const void *a,const void *b){
	return *(int *)a-*(int *)b;
}
int main(){
	long long n,m;
	scanf("%lld %lld",&n,&m);
	long long i,j,a[n];
	for(i=0;i<n;i++){
		scanf("%lld",&a[i]);
	}
	qsort(a,n,sizeof(a[0]),cmp);
	long long left=a[0];
	long long right=a[n-1];
	int p=0;
	while(left<=right){
		long long mid=(right+left)/2;
		long long sum=0;
		for(i=0;i<n;i++){
			if(a[i]>mid){
				sum+=a[i]-mid;
			}
		}
		if(sum<m){
			right=mid-1;
		}
		else if(sum>m){
			left=mid+1;
		}
		else{
			printf("%lld",mid);
			p=1;
			break;
		}
	}
	if(p==0){
		printf("%lld",left-1);
	} 
	return 0;
}

别人的代码:

别人写的二分代码:

 

while(left<=right){
		long long mid=(right+left)/2;
		long long sum=0;
		for(i=0;i<n;i++){
			if(a[i]>mid){
				sum+=a[i]-mid;
			}
		}
		if(sum<m){
			right=mid-1;
		}
		else{
			left=mid+1;
		}
}
	
		printf("%lld",left-1);
	

可以看出别人这个写法会更加简洁。这个代码没有分sum>m和sum==m时的情况。直接将这两种情况合在一起,进行left=mid+1;的操作。怎么理解呢?

如果遇到sum==m的情况时,此时mid所指的那个数就是我们的锯片高度,我们继续执行left=mid+1;此时left和right所指的区间都不是我们想要的,接下来会一直进入sum<m的条件下,right会一直往左移,left不变位置, 直到right移到left左边一位,结束循环,我们输出的left-1就是我们当时想要的mid值。

如果一直没有出现sum==m的情况,说明没有刚刚好我们要的锯片高度的存在,说明我们只能取那个最节省树木的锯片高度,二分查找会帮我们不断缩小筛选区间,所以当right<left时出循环,left-1就是我们要的最节省的锯片高度。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值