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

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/ssss1223ss/article/details/60137238

朋友最近面试某公司,被一道笔试题难住,最后被无情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;
}

猜你喜欢

转载自blog.csdn.net/ssss1223ss/article/details/60137238