二分法之将答案转化成判定

二分法的简单用法为 查找单调数组里的数据。
详见:
https://www.cnblogs.com/kingbuffalo/p/15500058.html

此外,如果一个问题非常难以解决,但又知道应该问题的答案具有如下性质:

  1. 存在 -∞~s 之前,答案合法 ; s~+∞:不合法。
  2. 答案具有单调性。

那么,也可以通过二分法来找到答案。
伪代码如下:

left = 答案下限
right = 答案上限
while( left < right ){
        mid = (left + right)/2;
        if ( valid(mid )) left = mid+1;
        else right = mid -1;
}
//left -1 为 最佳答案

以下为 poj 2456 ac代码

#define NMAX 100005

int stalls[NMAX];

//为每个cow查找合适的位置,如果可以都找到,则是合法的
bool isValid(int ans,int N,int C){
	int left  = 1;
	int right = N-1;
	int findCnt = 1;
	int preIdx = 0;
	for( int i=1;i<C;++i ){
		int searchV = stalls[preIdx] + ans;
		right = N-1;
		while(left<=right){
			int mid = left+((right-left)>> 1);
			if ( searchV < stalls[mid] ) right = mid-1;
			else left = mid+1;
		}
		if ( stalls[left-1] - stalls[preIdx] >= ans ){
			findCnt ++;
			preIdx = left-1;
		}else{
			if ( stalls[left] - stalls[preIdx] >= ans ){
				findCnt ++;
				preIdx = left;
			}
		}
	}
	return findCnt >= C;
}

int main(){
	int N,C;
	scanf("%d%d",&N,&C);
	for( int i=0;i<N;++i ) scanf("%d",&stalls[i]);
	sort(stalls,stalls+N);
	int left = 1;
	int right = stalls[N-1]-stalls[0];
	while( left <= right ){
		int mid = left+((right-left) >> 1);
		if ( isValid(mid,N,C) ){
			left = mid+1;
		}else{
			right = mid-1;
		}
	}
	printf("%d\n",left-1);

	return 0;
}
上一篇:C语言中阶第四篇:分支与循环语句练习,求阶乘的多种方法(两层for循环求阶乘)、二分查找、字符串汇聚以及模拟用户登录


下一篇:LeetCode 面试题17.21 直方图的水量