二分查找及其变种问题

基本的二分查找

代码实现

非递归版本

#include<stdio.h>
int binary_search(int a[], int low,int high,int val)
{
    int mid;
    while(low<=high)
    {
        mid = low + high / 2;
        if(a[mid]>val)
        {
            high = mid - 1;
        }else if(a[mid]==val)
        {
            return mid;
        }else
        {
            low = high + 1;
        }

    }
    return -1;
}
int main()
{
    int a[5] = {1, 3, 5, 7, 9};
    printf("%d", binary_search(a, 0, 4, 5));
}

递归版本

#include <stdio.h>
int binary_search(int a[], int low, int high, int val)
{
    int mid;
    if (low <= high)
    {
        mid = low + high / 2;
        if (a[mid] > val)
        {
            return binary_search(a, low, mid - 1, val);
        }
        else if (a[mid] == val)
        {
            return mid;
        }
        else
        {
            return binary_search(a, mid + 1, high, val);
        }
    }
    if(low>high)
    {
        return -1;
    }
}
int main()
{
    int a[5] = {1, 3, 5, 7, 9};
    printf("%d", binary_search(a, 0, 4, 10));
}

二分查找比较简单就不再赘述。

变种问题

查找第一个等于给定值的元素
过程描述

普通的二分查找只能保证找到给定值元素的位置,并不能保证位置唯一或者出现的顺序,通过改变二分查找的代码部分内容,可以实现。

在这里插入图片描述
当我们a[mid]=val的时候,此时我们就可以通过判断mid前面一位的元素是否也为给定值,如果是的话,那就将high移动到mid前一位(图上情况是正好只有mid前一位为指定值,实际上a[1]也可能为给定值),在low和high(mid-1)之间再次二分查找。如果mid前一位元素不等于给定值,说明mid就是第一次出现的位置(因为这是个有序的数组,前面一位如果不等于的话,那就一定小于给定值)

代码实现
#include<stdio.h>
int binary_search(int a[], int low,int high,int val)
{
    int mid;
    if(low<=high)
    {
        mid = low + high / 2;
        if(a[mid]>val)
        {
            binary_search(a, mid + 1, high, val);
        }else if(a[mid]==val)
        {
            if (a[mid - 1] == val)
            {
                return binary_search(a, low, mid - 1, val);
            }
                return mid;
        }else
        {
            high = mid - 1;
            return binary_search(a, low, mid-1, val);
        }

    }
    if(low>high)
    {
		return -1;
    }
    
}
int main()
{
    int a[6] = {1, 2, 3, 3, 3, 5};
    printf("%d", binary_search(a, 0, 5, 3));
}

在这里插入图片描述

查找最后一个等于给定值的元素
过程描述

理解了第一种变体,这一种就很好理解了,就不做过多解释。

代码实现
#include<stdio.h>
int binary_search(int a[], int n,int val)
{
    int low = 0;
    int high = n - 1;
    int mid = 0;
    while(low<=high)
    {
        mid = (low + high) / 2;//记得打括号还可以转化成别的两种写法1.high-(high-low)/2
        if(a[mid]>val)			//2.low + ((high - low) >> 1).可以加快运行速度,防止溢出
            high = mid - 1;
        else if(a[mid]==val)
        {
            if((a[mid+1]!=val)||(mid==n-1))
            {
                return mid;
            }else
            {
                low = mid + 1;
            }
        }else
        {
            low = mid + 1;
        }

    }
    return -1;
}
int main()
{
    int a[6] = {1, 2, 3, 3, 3, 5};
    printf("the last position:%d", binary_search(a, 6,3));
}

在这里插入图片描述

查找第一个大于等于给定值的元素
过程描述

对于这种进行一下解释。如图所示。
在这里插入图片描述

代码实现
#include<stdio.h>
int binary_search(int a[], int n,int val)
{
    int low = 0;
    int high = n - 1;
    int mid = 0;
    while(low<=high)
    {
        mid = (low + high) / 2;
        if(a[mid]<val)
        {
            low = mid + 1;
        }else
        {
            if(a[mid-1]<val||mid==0)
            {
                return mid;
            }else
            {
                high = mid - 1;
            }
        }

    }
    return -1;
}
int main()
{
    int a[6] = {1, 2, 3, 3, 3, 5};
    printf("the last position:%d", binary_search(a, 6,4));
}

在这里插入图片描述

查找最后一个小于等于给定值的元素
过程描述

理解了上述图片,这个就不需要多余赘述了,可以自己推理一下检验一下是否掌握了

代码实现
#include<stdio.h>
int binary_search(int a[], int n,int val)
{
    int low = 0;
    int high = n - 1;
    int mid = 0;
    while(low<=high)
    {
        mid = (low + high) / 2;
        if(a[mid]<=val)
        {
            if(a[mid+1]>val ||mid==n-1 )
            {
                return mid;
            }else{
            low = mid + 1;
            }
        }else
        {
            high = mid - 1;
        }

    }
    return -1;
}
int main()
{
    int a[6] = {1, 2, 3, 3, 3, 5};
    printf("the last position:%d", binary_search(a, 6,4));
}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值