• 二分查找


    1.猜数

    (以下故事纯属虚构,如有雷同,不胜荣幸)

    小海:“小涵,你现在心里想一个1000以内的数,信不信我最多只要问你十个问题,我就能猜出这个数是什么?”

    小涵:“真的么? 我不信。”

    小海:“不信? 那就来试一试怎么样?”

    小涵:“哟,还来劲了,来啊。”

    小海:“那现在给你十秒钟时间想这个数字。”

    小涵:“.......(沉默)”

    小海:“10,9,8,...”

    小涵:“别点啦,我已经想好了。”

    小海:“这么快啊,不多想会儿? 不然等下你又说我作弊。”

    小涵:“我.......(-_-||),快点开始吧。”

    小海:“OK,那现在开始了,你想的数比500大吗?”

    小涵:“嗯,对,比500大。”

    小海:“嗯,那好,这个数比750大吗?”

    小涵:“没有。”

    小海:“比625大吗?”

    小涵:“没有呢。”

    小海:“比562大吗?”

    小涵:“没有,你怎么老是问同样的问题,能不能换个有趣一点的。”

    小海:“这个问题怎么就无趣了,继续,这个数比531大吗?”

    小涵:“没有,你不能换个有新意的问法吗? emmmmm”

    小海:“奥,要有新意啊,那这个数比428加87更大吗?”

    小涵:“这。。。428加87.......,我...,等我算一下。”

    小涵:“428加87等于515,比515更大,你还是用原来的问法吧。-_—”

    小海:“哈哈哈哈哈哈,你不是要有趣的问法吗,那这个数比523大吗?”

    小涵:“这个叫有趣...(小声),额,没有,比523更小。”

    小海:“昂,就要接近真像了,这个数比519更大吗?”

    小涵:“嗯嗯,比他更大。”

    小海:“这个数有比521更大吗?”

    小涵:“不会做真的能猜出来吧。。。(心想),嗯,没。”

    小海:“这个数有比520更大吗?”

    小涵:“没有。(假装镇定)”

    小海:“奥,这样啊。这个数是520”

    (场面突然升温)

    小涵:“嗯呢,(3秒的沉默),520。”

    (小海凝望着小涵)

    小海:“怎么样,我厉害吧。”

    小涵:“(石化4秒)?????????????????? 我 ..... , 你....(老娘话都到这儿了,你........)”

    小海:“嘿嘿,想学吗??”

    小涵:“(死亡微笑)再见。”

    (小涵转身走了)

    小海:“嗯? 喂! 不学就不学呗,干嘛走啊??? 我是说错了什么吗???(默默追上了小涵)”

    ......

    .....

    ....

    ...


    2.情侣的毁灭能手:二分

    不管你信不信,上面小海跟小涵玩的小游戏就是二分查找的核心。

    在这个游戏中,小涵心中想的数其实就是我们要在有序数字序列中查找的x,而小海说的1000内任意数字其实就是序列的长度。

    这个算法的核心思想就是不断地用当前序列区间中点的值value与x比较,若x比中间值value大,则在当前区间的右半区间继续查找x,否则在当前区间的左半区间查找,直到x被找出来。

    每一次操作,都能减少当前区间一半的查找量。 这样也就使得查找的效率大大提高。

    举个栗子:

    假设有序数字序列a为: 1 5 14 21 29 31 34 35

    需要查找的数x为: 14

    假设该数字序列下标从1开始,则序列区间为[1,8]

    设l为区间左端点,r为区间右端点。

    初始情况l = 1, r = 8,中点mid = (l+r)/ 2 = (1+8)/ 2 = 4 (C语言中用int直接取整)

    将中点的值a[mid] = a[4] = 21 与 x = 14进行对比

    x < a[mid] 成立

    则在当前区间的左半边进行查找,令l = l = 1,r = mid-1 = 3

    那现在的区间是[1,3]

    序列为:1 5 14

    重复上述过程

    mid = (l+r) / 2 = (1+3) / 2 = 2

    a[mid] = 5

    x = 14

    x < a[mid] 不成立

    x > a[mid] 成立

    所以令l = mid + 1 = 3, r = r = 3

    新缩小后的区间为[3,3]

    序列为:14

    mid = (l+r) / 2 = (3+3)/2 = 3

    a[mid] = 14

    x = 14

    x < a[mid] 不成立

    x > a[mid] 不成立

    x == a[mid] 成立

    令position = mid = 3

    所以最后寻找得到x的位置是3


    3.C语言代码

    #include<stdio.h>
    
    int main()
    {
        int a[100],i,x,n;
        scanf("%d",&n);
        for(i = 1; i <= n; i++)
            scanf("%d",&a[i]);
        scanf("%d",&x);
        
        int l = 1,r = n,mid,pos = -1;
        
        do{
            mid = (l+r)/2;    //序列下标中点计算
            if(x < a[mid])
                r = mid-1;   // 缩小区间,在当前区间左边查找
            else if(x > a[mid])
                l = mid+1;   //在当前区间右边查找
            else {          //找到就退出循环
                pos = mid;
                break;
            }
        }while(l <= r);
        
        if(pos == -1)printf("Not find!
    ");      //pos初始化的时候是-1,如果该变量没有被改变过,则序列中没有这个元素
        else printf("position is %d
    ",pos);
        return 0;
    }
    

    该程序的输入是序列长度n,有序序列a,以及待查元素x。

  • 相关阅读:
    gTest&gMock learning
    机器学习 delay learning
    c++ learning
    2017 湘潭邀请赛&JSCPC G&J
    mapreduce&GFS&bigtable learning
    golang learning
    高斩仙的北京历险记
    python learning
    Codeforces Round #448 (Div. 2) B
    python之callable
  • 原文地址:https://www.cnblogs.com/bingdada/p/11260962.html
Copyright © 2020-2023  润新知