二分搜索应用(旋转数组)——C语言

    出处——《剑指offer》

    题目:把一个数组最开始的若干个元素搬到数组的末尾,称之为数组的旋转。输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素。例如数组{3, 4, 5, 1, 2}为{1, 2, 3, 4, 5}的一个旋转,该数组的最小值为1。

    1.用遍历数组的方法来实现

int MinInOrder( int num[], index1, index2 )        /*index1为数组起始位置,index2为数组终止位置*/

{

    int result = num[ index1 ];

    int i;

    for( i = index1 + 1; i <= index2; i++ )

    {

        if( result > num[i] )

            result = num[i];

    }

    return result;

}

    算法复杂度O(n)

    2.若能够使用二分搜索实现可以使算法复杂度为O(logn)

    书中有详细的讲解,跟一般的二分搜索类似,但由于不是查找特定的数,而是要找到最小的数,因此要找到如何能够确定最小数的方法。根据旋转数组的特点,可以将其看作两个递增数组的组合,且左边数组的所有元素都大于右边数组,最小数所在的位置为右边数组的第一位。

    设定三个指针i1,i2以及mid,使得i1始终处在左边数组中,i2始终处在右边数组中, mid为中间数,通过i1,i2,mid元素间的大小关系来逐步确定最小数的位置。

    例如:若num[mid] >= num[i1]表明mid在左边数组中,那么令i1 = mid就可以使得i1趋近于左边数组末尾;若num[mid] <= num[i2]表明mid在右边数组中,此时则可令i2 = mid。

    最终当i2 - i1 == 1时,i2就为最小元素的位置。

int Min( int num[], int length )        /*length为数组长度*/

{

    int i1, i2, mid;

    i1 = 0;

    i2 = length - 1;

    while( num[i1] >= num[i2] )        /*保证i1,i2处在不同的子数组中*/

    {

        if( i2 - i1 == 1 )

            return num[i2];

        mid = ( i1 + i2 ) / 2;

        if( num[mid] >= num[i1] )

            i1 = mid;

        if( num[mid] <= num[i2] )

            i2 = mid;

    }

    return num[i1];        /*完全递增的数组也是旋转数组的一种,当出现这种情况时,由于num[i1] < num[i2]使得循环不执行,此时返回数组首元素*/

}

    不过上面的程序面对一些特例时会出现问题,如数组{ 1, 0, 1, 1, 1 },会出现num[i1] = num[i2] = num[mid] = 1的情况,此时循环中的两个if语句中的判断条件都为真,因此当第一次循环结束后就会出现i1 = i2 = mid的情况,使得循环无限执行。因此需要将这种情况考虑到函数中。

int Min( int num[], int length )      

{

    int i1, i2, mid;

    i1 = 0;

    i2 = length - 1;

    while( num[i1] >= num[i2] )       

    {

        if( i2 - i1 == 1 )

            return num[i2];

        mid = ( i1 + i2 ) / 2;

        if( num[i1] == num[i2] && num[i1] == num[mid] )        /*出现i1, i2, mid三个元素都相等的情况则采用顺序搜索的方法*/

            return MinInOrder( num, i1, i2 );

        if( num[mid] >= num[i1] )

            i1 = mid;

        if( num[mid] <= num[i2] )

            i2 = mid;

    }

    return num[i1];        

}

 

 

posted @ 2012-09-12 17:08  糙哥  阅读(1014)  评论(0编辑  收藏  举报