旋轉有序數組的二分查找


要求

  給定一個沒有重復元素的旋轉數組(它對應的原數組是有序的),求給定元素在旋轉數組內的下標(不存在的返回-1)。

例子

有序數組{0,1,2,3,4,5,6,7}對應的旋轉數組為{3,4,5,6,7,0,1,2}(左旋、右旋效果相同)。

  • 查找元素5,返回結果2;
  • 查找元素8,返回結果-1。

分析

  可以輕易地想到遍歷一遍O(n)時間可以得到結果,但是並不是最好的結果;利用有序的特點,可以輕易的想到二分查找的方法。經過旋轉后的數組總是可以分為兩個有序序列,如下圖所示。旋轉數組分成了紅藍兩段有序序列。

                                                            

  可以看出中間位置m(m')的兩邊必然有一個是有序的,如果是m則左邊有序;如果是m'則右邊有序;如下可以看出。

                                                            

  總結規律:每次根據L和R求出m后,m左邊[L, m-1]和右邊[m+1, R]這兩部分中至少一個是有序的。

       (1)arr[m]=X,返回m

       (2)arr[m]<arr[R],位於m'位置右側是有序的;當arr[m']<X<arr[R]時,則L=m'+1,否則R=m'-1。

       (3)arr[m]>=arr[R],位於m位置左側是有序的;當arr[L]<X<arr[m]時,則R=m-1,否則L=m+1。

參考代碼

 數組的旋轉點擊這里查看。

int BSearch(int *arr, int len, int X){ int L = 0, R = len - 1; int m; while (L <= R){                         //循環條件
        m = (L + R) / 2; if (arr[m] == X)                    //找到了,終止
            return m; if (arr[m] < arr[R]){               //右側有序
            if (arr[m] < X && arr[R] >= X){ L = m + 1; } else R = m - 1; } else{                               //左側有序
            if (arr[m] > X && arr[L] <= X){ R = m - 1; } else L = m + 1; } } return -1;                               //循環結束,沒找到。
}

擴展

  上面要求的是沒有重復元素,現在稍微擴展一下,可以有重復的元素,其它的要求不變。

思路:大致思路和原來相同,只不過相等的情況單獨處理。找到的元素位置,並不一定是第一次出現的位置。

  • arr[L]<arr[m];左邊有序
  • arr[L]>arr[m];右邊有序
  • arr[L]=arr[m];相等,特殊處理,++L(L=m+1也可以)。

和arr[R]比較也可以。

 

int BSearch(int *arr, int len, int X){ int L = 0, R = len - 1; int m; while (L <= R){                         //循環條件
        m = (L + R) / 2; if (arr[m] == X)                    //找到了,終止
            return m; if (arr[m] < arr[L]){               //右側有序
            if (arr[m] < X && arr[R] >= X){ L = m + 1; } else R = m - 1; } else if (arr[m] > arr[L]){          //左側有序
            if (arr[m] > X && arr[L] <= X){ R = m - 1; } else L = m + 1; } else                                //相等情況
            L = m + 1; } return -1;                              //循環結束,沒找到。
}

 

2015-10-14 15:32:56

 


免責聲明!

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



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