题目:
思路:
锯片的高度是处于这一排中最矮的树和最高的树之间的,所以我们可以想到先对这一排树先进行排序,然后让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就是我们要的最节省的锯片高度。