简单二分

二分是一个比较基础的算法,花了一点时间实现了它。
简单介绍一下题目的要求,输入一个整数n,然后输入n个数,再输入你要查找的数,判断一下是否在这些数里面,在的话输出Yes,否则输出No。

代码:

#include<cstdio>
#include<iostream>
#include<stdlib.h>
#include<string.h>
#include<algorithm>
using namespace std;
int get_number[105];
int main()
{
    int i,j;
    int n; //length
    int wanna; //the number want to find
    while(scanf("%d",&n)!=EOF)
    {
        memset(get_number,0,sizeof(get_number));

        for(i=1;i<=n;i++)
        {
            scanf("%d",&get_number[i]);
        }

        sort(get_number+1,get_number+n+1);

        scanf("%d",&wanna);

        bool is_found=false;

        int right=n,left=1;
        int mid=(right+left)/2;

        if(wanna==get_number[right] || wanna==get_number[left]) 
        {
            printf("Yes\n");
            continue;
        }

        while(left+1!=right)
        {
            if(get_number[mid]==wanna)
            {
                is_found=true;
                break;
            }

            if(get_number[mid]>wanna)
            {
                right=mid;
                mid=(right+left)/2;
            }
            else if(get_number[mid]<wanna)
            {
                left=mid;
                mid=(right+left)/2;
            }
        }

        if(is_found)printf("Yes\n");
        else printf("No\n");
    }
    return 0;
}
/*
7
131 2 31 283 221 39 18
*/

while循环的条件判断是left+1!=right,因为我在二分过程中直接把mid赋给left或right。

另外一种的二分:


bool bSearch(int a[],int num,int wanna)
{
    int left=1,right=num,mid;
    while(left<=right)
    {
        mid=(left+right)>>1;//右移一位 /=2; 
        if(a[mid]==wanna)return true;
        else if(a[mid]<wanna)left=mid+1;
        else right=mid-1;
    }
    return false;
}

需要注意的一点是,mid=(left+right)>>1,利用右移的方法更新mid。

参阅了一些朋友的博客,发现这个算法还有可以优化的地方,如下。

  • 1.首先, 如果序列中有多个相同的元素时,查找的时候不见得每次都会返回第一个元素的位置, 比如考虑一种极端情况:序列中都只有一个相同的元素,那么去查找这个元素时,显然返回的是中间元素的位置.
  • 2.其次, 前面给出的算法中,每次循环体中都有三次情况,两次比较,有没有办法减少比较的数量进一步的优化程序?

解决代码:

int search4(int array[], int n, int v)
{
    int left, right, middle;

    left = -1, right = n; //开区间

    while (left + 1 != right) //防止死循环
    {
        middle = left + (right - left) / 2; //防止溢出

        if (array[middle] < v)
        {
            left = middle;
        }
        else
        {
            right = middle;
        }
    }

    if (right >= n || array[right] != v)
    {
        right = -1;
    }

    return right;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值