从2段已序的数组中查找某一个数的算法

来源:互联网 发布:网络大电影如何赚钱 编辑:程序博客网 时间:2024/06/01 18:53

朋友最近面试某公司,被一道笔试题难住,最后被无情pass了。题目大致是:int a[] 由2个已序且范围无交叉的序列组成,比如4,5,6,7,1,2,3,从中查找指定的数。要求时间复杂度小于O(N)。


算法思路

首先想到的是折半查找,时间复杂度应该为O(log N)。假设数组起始位置为x和y,折半位置为h,2个序列边界为*,查找数的位置为n。

数组表示为:

|---------->|---------->|x           h           y

由a[h]与a[x],a[y]比较可知,序列边界*在h的左边还是右边。分为两种情况:
1. 当a[h] < a[x]时,序列边界*在h的左边

|-----><----->|---------->|x      *      h           y

此时位置n分三种情况,只有当a[n] > a[h] 且 a[n] <= a[y]时下一次将在h的右边开始查找。

  1. 当a[h] > a[x]时,序列边界*在h的右边
|---------->|-----><----->|x           h      *      y

此时位置n分三种情况,只有当a[n] >= a[x] 且 a[n] < a[h]时下一次将在h的左边边开始查找。


代码实现

int find_in_two_sort_part(int a[], int len, int n){    int begin = 0;    int end = len - 1;    while (begin <= end)    {        // |---------->|---------->|        // x           h           y        int half = (begin + end) >> 1;        if (n == a[half])        {            return half;        }        // |-----><----->|---------->|        // x      *      h           y        if (a[half] < a[end])        {            // |------><----->|-----*----->|            // x      *      h      n      y            if ((n > a[half]) && (n <= a[end]))            {                begin = half + 1;            }            else            {                end = half;            }        }        // |---------->|-----><----->|        // x           h      *      y        else if (a[half] > a[begin])        {            // |----*----->|-----><----->|            // x     n      h      *      y            if ((n >= a[begin]) && (n < a[half]))            {                end = half;            }            else            {                begin = half + 1;            }        }        else        {            return -1;        }    }    return -1;}
0 0
原创粉丝点击