欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

二分查找几种小小的变形

程序员文章站 2024-03-20 10:28:58
...

首先,二分查找的时间复杂度是O(logn)

这里不探究这个时间复杂度的原因。因为我自己还很菜,现在没有搞懂呢。

主要是想区分并理解一下关于二分查找发小小的几个变形。

再首先,下面是最基础的二分查找,就是单纯的查找一个正确值。

int binarySerach(int a[], int key)
{
    int left = 1, right = a.length;//a.length指的是数组a的长度
    while(left <= right)
    {
        int mid = (left + right) >> 2;
        if(a[mid] > key)
            right = mid - 1;
        else if(a[mid] < key)
            left = mid + 1;
        else 
            return mid;
    }
    return -1;
}

再下面的呢,就是几种小小的变形啦。

第一种:查找第一个与key相等的值,先代码,在解释。

int binarySerach(int a[], int key)
{
    int left = 1, right = a.length;//a.length指的是数组a的长度
    while(left <= right)
    {
        int mid = (left + right) >> 2;
        if(a[mid] >= key)
            right = mid - 1;
        else
            left = mid + 1;
    }
    if(a[left] == key && left <= a.length)
        return left;
    return -1;
}

其实自己举个看得过去的例子,模拟推理一遍,加上自己的总结,差不多就懂得差不多了。

比如,我举得例子就是这么一串数字:1 2 3 4 4 4 5,总共七个数。

在上面刚刚写的变形中,相当于就是要得出第一个4也就是a[4];

left 最后是停在 a[4] 这个位置,而right 最后停在了a[3]的位置。

最后就输出所要求的数字,即left最后的值。


第二种:查找最后一个与key相等的值

int binarySerach(int a[], int key)
{
    int left = 1, right = a.length;//a.length指的是数组a的长度
    while(left <= right)
    {
        int mid = (left + right) >> 2;
        if(a[mid] <= key)
            left = mid + 1;
        else
            right = mid - 1;
    }
    if(a[right] == key && right >= 1)
        return right;
    return -1;
}

不用仔细就看会发现,和上一个没啥区别的,上一个懂了,这个也就顺理成章了。

但仔细看就会发现还是有很多细微的区别的,虽然细微,但不可或缺。我写这篇博客的时候,就因为一些小小的差别错了几次。


第三种:查找第一个大于key的元素

int binarySerach(int a[], int key)
{
    int left = 1, right = a.length;
    while(left <= right)
    {
        int mid = (left + right) >> 2;
        if(a[mid] <= key)
            left = mid + 1;
        else 
            right = mid - 1;
    }
    return left;
}

从这个开始后面的就逐渐有规律了,比如这个,跟第二种小变化其实是一样的,只不过一个是要的right值,另一个要的是left值

在有些大犇(ben)博客里呢,规律没有体现出来,情况放的有点乱,我的理解是大佬们不需要靠规律,想着就可以写出来了。

但说实话我刚会的时候靠着规律背的,时间长了就自行理解了。所以对我这种菜鸟,规律还是蛮重要的。但是呢,最好还是自己捋清楚,不能靠规律。要勤思考。嗯~ o(* ̄▽ ̄*)o

第四种:查找最后一个小于key的元素

int binarySerach(int a[], int key)
{
    int left = 1, right = a.length;
    while(left <= right)
    {
        int mid = (right + left) >> 2;
        if(a[mid] >= key)
            right = mid - 1;
        else
            left = mid + 1;
    }
    return right;
}

这种情况跟上面一个的简直一mu子一样。


第五种:查找最后一个小于或者等于key的元素。

int binarySerach(int a[], int key)
{
    int left = 1, right = a.length;
    while(left <= right)
    {
        int mid = (right + left) >> 2;
        if(a[mid] <= key)
            left = mid + 1;
        else right = mid - 1;
    }
    return right;
}

最后一个小于key的元素和最后一个等于key的元素为什么组成cp了呢,最直白的解释就是

都是最后一个的属性

那隐晦的解释呢,就要靠自己推一推了,举个例子,推一边,就ok了。


第六种:查找第一个大于或者等于key的元素

int binarySerach(int a[], int key)
{
    int left = 1, right = a.length;
    while(left <= right)
    {
        int mid = (left + right) >> 2;
        if(a[mid] >= key)
        {
            right = mid - 1;
        }
        else
        {
            left = mid + 1;
        }
    }
    return left;
}

这个就可以参考上面一个的了,虽然应该是没什么好参考的.....

就这些了,小变化应该就这些了,还有的大变化的,下次再喷。


这是我参考的博客:https://www.cnblogs.com/luoxn28/p/5767571.html