二分(整数二分和浮点数二分)

二分(整数二分和浮点数二分)

整数二分

知识点

有单调性一定可以二分,可以二分不一定有单调性
二分的本质是右半边满足这种性质,左半边不满足这种性质
如果可以找到这样一种性质,使数组一分为二,即可以找到边界点位置

二分左半边的右边界点

1.步骤

1.找中间值 mid=(l+r+1)/2
2.判断中间值是否满足性质
假设性质是左半边的性质

if(check(mid)){
	mid在左半区间,所以要寻找的边界点范围为**[mid,r]** 
	因为mid可能为左半边的右边界点即要寻找的边界点,所以左闭 
               即**更新 l=mid** 
}
else{
	mid在右边区间,所以要寻找的边界点范围为**[l,mid-1]** 
	因为mid不满足左半边的性质,所以mid不可能是左半边的右边界点,所以右边取不到mid 
               即**更新 r=mid-1**	
}
2.代码(带注释)
// 区间[l, r]被划分成[l, mid - 1]和[mid, r]时使用:	
bool check(int x) {/* ... */} // 检查x是否满足左半边性质性质
int zs_erfen_1(int l, int r) // 整数二分模板1 
{
    while (l < r){
        int mid = (l + r + 1) >> 1; //当l=mid这种情况时 中间值要补上+1  例如当l=r-1时,mid=l,此时如果check为true,会出现死循环,正常应该mid=r,所以要+1 
        if (check(mid)){
			l = mid;
		} 
        else{
			r = mid - 1;
		} 
    }
    return l;
}
3.代码(不带注释)
// 区间[l, r]被划分成[l, mid - 1]和[mid, r]时使用:	
bool check(int x) {
    
}
int zs_erfen_1(int l, int r) 
{
    while (l < r){
        int mid = (l + r + 1) >> 1; 
        if (check(mid)){
			l = mid;
		} 
        else{
			r = mid - 1;
		} 
    }
    return l;
}

二分右半边的左边界点

1.步骤

1.找中间值 mid=(l+r)/2
2.判断中间值是否满足性质
假设性质是右半边的性质

if(check(mid)){
	mid在右边区间,所以要寻找的边界点范围为**[l,mid]** 
	因为mid不满足左半边的性质,所以mid可能是右半边的左边界点,所以右闭 
	即**更新 r=mid**
}
else{
	mid在左半区间,所以要寻找的边界点范围为**[mid+1,r]** 
	因为mid不可能为右半边的左边界点即要寻找的边界点,所以取不到mid 
	即**更新 l=mid+1**
}
2.代码(带注释)
// 区间[l, r]被划分成[l, mid]和[mid + 1, r]时使用:
bool check(int x) {/* ... */} // 检查x是否满足右半边性质
int zs_erfen_2(int l, int r) // 整数二分模板2
{
    while (l < r){
        int mid = (l + r) >> 1;
        if (check(mid)){
			r = mid;    // check()判断mid是否满足性质
		}
        else{
        	l = mid + 1;	
		}
    }
    return l;
}
3.代码(不带注释)
// 区间[l, r]被划分成[l, mid]和[mid + 1, r]时使用:
bool check(int x) {
    
}
int zs_erfen_2(int l, int r)
{
    while (l < r){
        int mid = (l + r) >> 1;
        if (check(mid)){
			r = mid; 
		}
        else{
        	l = mid + 1;	
		}
    }
    return l;
}

浮点数二分

1.知识点

浮点数二分不需要考虑边界

2.步骤

1.确定eps 当两数差小到一定程度是则可认为找到数,一般为保留的小数位数多2
2.取中间值 double mid = (l + r) / 2
3.判断中间值是否满足左半边性质

if (check(mid)){
	r = mid;
} 
else{
	l = mid;
} 

4.直到边界范围小于eps即认为找到这个数

3.代码(带注释)

bool check(double x) {
    
} // 检查x是否满足右半边性质
double fds_erfen(double l, double r){ // 浮点数二分模板 
	//保留的小数位数多2 
    const double eps = 1e-6;   // eps 表示精度,取决于题目对精度的要求
    while (r - l > eps){ //当两数差小到一定程度是则可认为找到数 
        double mid = (l + r) / 2;
        if (check(mid)){ //满足右半边性质,在左边 
			r = mid;
		} 
        else{
			l = mid;
		} 
    }
    return l;
}

4.代码(不带注释)

bool check(double x) {
    
}
double fds_erfen(double l, double r){
    const double eps = 1e-6;
    while (r - l > eps){
        double mid = (l + r) / 2;
        if (check(mid)){ 
			r = mid;
		} 
        else{
			l = mid;
		} 
    }
    return l;
}
posted @ 2021-02-20 16:12  二氧化矽  阅读(298)  评论(0)    收藏  举报