二分查找

最近写一些程序的时候发现对二分查找还不是很熟练,所以整理了一下,统一了一下格式。

例如区间取左闭右闭,做除法时向左偏(保证不会出现死循环),以下是一些常见情况。

#include<bits/stdc++.h>
using namespace std;
int a[1005];

//递增序列第一个大于t的下标
int bin1(int l, int r, int t) //区间左闭右开,第一个大于t的值,若没有返回r+1。
{
    while (l < r)
    {
        int mid = (l + r) / 2; //计算结果向左偏,由于l会更新,而r可能不会更新陷入死循环
        if (a[mid] <= t)
        {
            l = mid + 1;
        }
        else
        {
            r = mid;
        }
    }
    if (a[l] <= t) l++;       //特判特殊情况
    return l;
}

//递增序列第一个大于等于t的下标
int bin2(int l, int r, int t) //区间左闭右开,第一个大于t的值,若没有返回r+1。
{
    while (l < r)
    {
        int mid = (l + r) / 2; //计算结果向左偏,由于l会更新,而r可能不会更新陷入死循环
        if (a[mid] < t)
        {
            l = mid + 1;
        }
        else
        {
            r = mid;
        }
    }
    if (a[l] < t) l++;       //特判特殊情况
    return l;
}

//递减序列第一个小于t的下标
int bin3(int l, int r, int t) //区间左闭右开,第一个大于t的值,若没有返回r+1。
{
    while (l < r)
    {
        int mid = (l + r) / 2; //计算结果向左偏,由于l会更新,而r可能不会更新陷入死循环
        if (a[mid] >= t)
        {
            l = mid + 1;
        }
        else
        {
            r = mid;
        }
    }
    if (a[l] >= t) l++;       //特判特殊情况
    return l;
}

//递减序列第一个小于等于t的下标
int bin4(int l, int r, int t) //区间左闭右开,第一个大于t的值,若没有返回r+1。
{
    while (l < r)
    {
        int mid = (l + r) / 2; //计算结果向左偏,由于l会更新,而r可能不会更新陷入死循环
        if (a[mid] > t)
        {
            l = mid + 1;
        }
        else
        {
            r = mid;
        }
    }
    if (a[l] > t) l++;       //特判特殊情况
    return l;
}

int main()
{
    int n = 0, u = 0;
    cin >> n;
    for (int i = 1; i <= n; i++) cin >> a[i];
    cin >> u;
    cout << bin1(1, n, u) << endl;
    cout << bin2(1, n, u) << endl;
    //cout << bin3(1, n, u) << endl;
    //cout << bin4(1, n, u) << endl;
    return 0;
}

 

posted @ 2022-04-05 23:18  y61329697  阅读(28)  评论(0)    收藏  举报