【二分查找】在排序数组中,找出给定数字的出现次数 以及二分其他应用

分析题目:数组是已排序好的,找出给定数字key出现的次数,

方法1、最直观的方法就是遍历一遍数组,时间复杂度O(N)

方法2、可以借助二分查找,时间复杂度为O(logN)
找出最左边出现的key出现的位置,找出最右边key出现的位置。

size_t getLow(int *array,int size, int k)
{
    size_t left = 0;
    size_t right = size - 1;
    while (left < right)
    {
        int mid = (left + right) / 2;
        if (array[mid] >= k)
            right = mid;
        else
            left = mid + 1;
    }
    return left;
}

size_t getRight(int *array, int size, int k)
{
    size_t left = 0;
    size_t right = size - 1;
    while (left < right)
    {
        int mid = (left + right) / 2;
        if (array[mid] <= k)
            left = mid;
        else
            right = mid -1;
    }
    return right;
}


int main()
{
    int arr[] = { 0, 1, 1, 2, 2, 2, 2, 4, 4, 4 };
    int size = sizeof(arr) / sizeof(*arr);
    size_t left = getLow(arr, size, 2);
    size_t right = getRight(arr, size, 2);
    size_t count = right - left + 1;
    return 0;
}

递归算法
注意:参数count为引用。

void getCount(int *array,int left,int right ,int k,int& count)
{
    if (left > right)
        return;
    int mid = (left + right) / 2;
    if (array[mid] == k)
    {
        ++count;
        getCount(array, left, mid - 1, k, count);
        getCount(array, mid + 1, right, k, count);
    }
    else if (array[mid] > k)
        getCount(array, left, mid - 1, k, count);
    else
        getCount(array, mid + 1, right, k, count);
}

二分查找

如果是开区间的话,right = length,left < right,right = mid.

//[] 闭区间
int BinSearch(int arr[],int length, int key)
{ 
    int left = 0;
    int right = length - 1;
    int mid = 0;

    while (left <= right)
    {
        mid = (left + right) >> 1;
        if (arr[mid] < key)
            left = mid + 1;
        else if (arr[mid] > key)
            right = mid - 1;
        else
            return mid;
    }
    return -1;
}

* 在有序数组中,查找第一个大于k的数字 upper_bound函数*

int FirstGreat(int *arr,int size,int k)
{
    int left = 0, right = size - 1;
    while (left <= right)
    {
        int mid = (left + right) / 2;
        if (arr[mid] <= k)
            left = mid + 1;
        else
            right = mid - 1;
    }
    return left < size ? left : -1;
}

有序数组中,查找第一个大于等于k的数字,lower_bound函数

int FirstGreatOrEqual(int *arr,int size,int k)
{
    int left = 0, right = size - 1;
    while (left <= right)
    {
        int mid = (left + right) / 2;
        if (arr[mid] < k)
            left = mid + 1;
        else
            right = mid - 1;
    }
    return left < size ? left : -1;
}

猜你喜欢

转载自blog.csdn.net/wenqiang1208/article/details/77887727