面試題:查找旋轉數組中的某一元素


題目:一個數組是由一個遞增數列右移若干位形成的,比如{4,5,1,2,3}是由{1,2,3,4,5}左移兩位形成的,在這種數組中查找某一個數。

這道題其實是前面介紹的一道題目:面試題8:旋轉數組的最小數字 的一個變種。

解題思路如下:

  1. 首先通過“面試題8:旋轉數組的最小數字”這道題目中獲取元素分裂點,時間復雜度為O(log(n))
  2. 因為旋轉數組是由遞增數組右移得到,因此旋轉數組中的第一個元素是整個數組的中間元素,比較待查找元素與第一個元素,如果待查找元素大於等於第一個元素,表明待查找元素在前半段有序數組中;如果不是這待查找元素在后半段數組中。
  3. 判斷待查找元素所在的有序數組以后,我們通過一個簡單的二分查找就可以找出元素所在位置,時間復雜度也是O(log(n))
  4. 總是時間復雜度為2個O(log(n)),所以時間復雜度還是O(log(n))。

代碼實例

View Code
#include<iostream>
#include<stdlib.h>
#include<stack>
#include<cassert>
using namespace std;

//函數聲明
int getSplitIndex(int arry[],int len);//獲取分裂點坐標
int BinarySearch(int arry[],int len,int value);//二分查找通用算法
int FindNumInRotatedArry(int arry[],int len,int value);//查詢元素位置

//二分查找算法,不使用遞歸,如果存在返回數組位置,不存在則返回-1
int BinarySearch(int arry[],int start,int end,int value)
{
    //如果傳入的數組為空或者數組長度<=0那么就返回-1。防御性編程
    if(arry==NULL||start>end)
        return -1;

    while(start<=end)//判斷清是否有=
    {
        int mid=start+(end-start)/2;
        if(arry[mid]==value)
            return mid;
        else if(value<arry[mid])
            end=mid-1;
        else
            start=mid+1;
    }
    return -1;

}

int getSplitIndex(int arry[],int len)//返回最小數的坐標
{
    if(arry==NULL||len<=0)
        return -1;

    int start=0;
    int end=len-1;
    while(start<end)
    {
        //如果首個元素小於最后一個元素,表明數組是排序的。
        if(arry[start]<arry[end])
            return start;

        //當start指針和end指針隔壁的時候,返回end指針就是最小元素的坐標
        if(end-start==1)
            return end;

        int mid=(start+end)/2;
        //如果arry[mid],arry[start]和arry[end]三個數相等,就只能使用順序查找
        if(arry[mid]==arry[start]&&arry[mid]==arry[end])
        {
            int index=start;
            for(int i=start+1;i<=end;i++)
            {
                if(arry[i]<arry[index])
                    index=i;
            }
            return index;
        }
        //如果中間元素小於末尾元素,那么表明中間元素在后半段數組中,修改end指針
        if(arry[mid]<arry[end])
        {
            end=mid;
        }
        //如果中間元素大於首元素,那么表明中間元素在前半段數組中,修改start指針
        else if(arry[mid]>arry[start])
        {
            start=mid;
        }
    }
    return -1;
}

int FindNumInRotatedArry(int arry[],int len,int value)//返回最小數的坐標
{
    if(arry==NULL||len<=0)
        return -1;

    int start=0;
    int end=len-1;

    int splitIndex=getSplitIndex(arry,len);//獲取分裂點坐標
    cout<<"分裂點坐標:"<<splitIndex<<endl;
    //比較待查找元素與第一個元素的大小,如果大於等於第一個元素表明待查找元素在前半段
    if(value>=arry[start])
    {
        end=splitIndex-1;
        return BinarySearch(arry,start,end,value);
    }
    else//否則在后半段查找
    {
        start=splitIndex;
        return BinarySearch(arry,start,end,value);
    }
    return -1;
}

void main()
{
    int arry[]={4,5,1,2,3};
    
    int len=sizeof(arry)/sizeof(int);

    int value=3;
    int index=FindNumInRotatedArry(arry,len,value);
    cout<<"查找數在數組中的位置:"<<index<<endl;

    system("pause");
}

程序輸出結果:

分裂點坐標:2
查找數在數組中的位置:4
請按任意鍵繼續. . .

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM