二分查找

一、二分查找

其本质就是找一个区间

二、整数二分

2.1. 查找左边界的模板

int findPrior(int left,int right,int target) {
	while (left < right) {
		int mid = (left + right) / 2;
		if (a[mid] >= target) right = mid;
		else left = mid + 1;
	}
	if (a[left] == target) return left;
	else return false;
}

2.2. 查找右边界模板

int findTail(int left, int right, int target) {
	while (left < right) {
		int mid = (left + right + 1) / 2;
		if (a[mid] <= target) left = mid;
		else right = mid - 1;
	}
	if (a[left] == target) return left;
	return false;
}

两个模板之间的区别在于,mid的边界取值问题。当找右边界时,mid=(left+right+1)/2,是为了防止其死循环,可以举例,当左指针在左边界,而右指针在其下一个位置,此时如果满足的是a[mid]<=target这一条件,左指针就会一直呆在左边界,此时陷入死循环。

如何记忆呢?答:看到left=mid,那么mid边界取值肯定是(left+right+1)/2,否则就是(left+right)/2。

2.2. 相关题目

#include<stdio.h>

int main() {
    int n;
    int q;
    int k;
    int a[100010];
    scanf("%d %d", &n, &q);
    for (int i = 0; i < n; i++)
        scanf("%d", a + i);
    while (q--) {
        scanf("%d", &k);
        int left = 0;
        int right = n;
        while (left < right) {
            int mid = (left + right) / 2;
            if (a[mid] >= k) right = mid;
            else left = mid + 1;
        }
        if (a[left] != k)
            printf("-1 -1\n");
        else {
            printf("%d ", left);
            left = 0; right = n - 1;
            while (left < right) {
                int mid = (left + right + 1) / 2;
                if (a[mid] <= k) left = mid;
                else right = mid - 1;
            }
            printf("%d\n", left);
        }
    }
}

三、浮点数二分

3.1. 相关题目

#include<stdio.h>
#include<math.h>

int main(){
    double n;
    scanf("%lf",&n);
    double left = -10000,right = 10000;
    while (right - left >= 1e-8) {
        double mid = (left + right) / 2;
        if (mid * mid * mid <= n) left = mid;
        else right = mid;
    }
    printf("%.6f",left);
    return 0;
}
posted @ 2023-11-07 20:06  彭乐祥  阅读(13)  评论(0编辑  收藏  举报