二分法(C#)

二分法(C#)

二分法思路:
将数组分成两部分,根据条件判断需要哪部分,舍弃掉不符条件的部分。继续在需要的部分里继续二分,直到得到结果。
适用:
二分法适合应用在有序数组中,对于特殊情况的无序数组也可以使用二分法
应用例子

1、在一个有序数组array[N]中,判断某个数(find)是否存在;

思路
利用二分法,找到中间值mid,mid与find比较
若mid=find 返回
若mid<find 在array[start]~array[mid-1]之间在二分,继续判断二分
若mid>find 在array[mid-1]~array[end]之间二分,继续判断二分
注:mid,中间位置。start,数组头。end,数组尾
代码实现

public bool FindNumber(int[] arr,int find)
{
    int start = 0;//记录每次二分的数组头部序号
    int end = arr.Length - 1;//记录每次二分的数组尾部序号
    int mid = (arr.Length - 1) / 2;//记录每次二分的数组中间序号
    while (start <= end)
    {
        if (find == arr[mid])
            return true;
        else if (find < arr[mid])
            end = mid-1;
        else
            start = mid+1;
        mid = (start + end) / 2;
    }
    return false;
}

2、在一个有序数组array[N]中,找到>=某个数(find)最左侧的位置
例:数组arr[1,1,2,2,2,4,4,4,5,5,5,6,6,7],找到>=4最左侧位置
输出:arr[5]
思路
(1) 利用二分法,找到中间值mid,mid与find比较(一定要二分到结束)
(2)若mid>=find 记录此时位置t,在array[start]~array[mid]之间二分(每次mid符合>=find,要将mid的序号与t比较,若是小于t,更新t为mid的序号)
(3)若mid<find 在array[mid]~array[end]之间二分。
代码实现

public int Findleft(int[] arr, int find)
{
    int start = 0;
    int end = arr.Length - 1;
    int mid = (arr.Length - 1) / 2;
    int t = arr.Length;//记录每一步中找到的位置
    while (end-start>1)
    {
        if (arr[mid] >= find)
        {
            if(t>mid)
                t = mid;
            end = mid;
        }
        else if (arr[mid] < find)
        {
            start = mid;
        }
        mid = (start + end) / 2;
    }
    return t;
}

3、在一个无序数组array[N],限定数组array相邻数不相等,局部最小值问题

局部最小值定义:
array[0]<array[1],array[0]为局部最小值
array[N-1]<array[N-2],array[N-1]为局部最小值
array[i]<array[i-1]且array[i]<array[i+1],array[i]为局部最小值

思路
(1)先判断array[0]和array[N-1]处是不是局部最小值,若是则返回,若都不是则此时数组中元素大小状态如下图。
在这里插入图片描述
所以根据上图可知数组内一定存在局部最小值。

(2)进行一次二分,找到中间值mid,让mid与左右比较。
若array[mid]<array[mid-1]&&array[mid]<array[mid+1],则array[mid]为局部最小值,返回即可。
若array[mid]>array[mid-1],下图显示了数组当时的大小趋势,此时array[start]到array[mid]之间一定有局部最小值,在array[start]——array[mid]之间在二分。下图是大小状态。
在这里插入图片描述
同理,若array[mid]>array[mid+1],则array[mid]到array[end]之间一定有局部最小值,在array[mid]——array[end]之间二分,继续二分。
代码实现

public int FindMin(int[] arr)
{
    int start = 0;
    int end = arr.Length - 1;
    int mid = (arr.Length - 1) / 2;
    if (arr[0] < arr[1])
        return 0;
    else if (arr[arr.Length - 1] < arr[arr.Length - 2])
        return arr.Length - 1;
    else
    {
        while (start < end&&mid!=0&&mid!=arr.Length-1)
        {
            if (arr[mid] < arr[mid - 1] && arr[mid] < arr[mid + 1])
                return mid;
            else if (arr[mid] > arr[mid - 1])//当中间的值及大于左边,又大于右边(左右两侧都有局部最小值的时候,优先取前面的局部最小值)
                end = mid;
            else if (arr[mid] > arr[mid + 1])
                start = mid;
            mid = (end + start) / 2;
        }
    }
    return -1;
}

如有问题,欢迎留言ヽ(✿゚▽゚)ノ

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值