旋轉數組中的最小數字

旋轉數組中的最小數字

  若是用直接查找的方法也就是一個一個比的方法(O(n)級別),雖然很容易解決,但顯然根據旋轉數組的規律,希望有更好時間效率的算法來解決。

  顯然旋轉數組可以用二分查找的方法來實現,考慮上面的例子,旋轉數組中的第一個數一定是大於最後一個數的,然後要找的最小的數一定是兩個遞增序列的分界線(此數的左邊遞增,右邊也遞增),利用二分查找的思想,設置三個指針分別指向數組的開始(begin),結尾(end),和中間(mid),然後分析過程如下:

但是注意要考慮到的幾種特殊條件:

1、若初始數組移動的是前0個元素,這也符合旋轉數組的要求,即這種旋轉數組本來就是排好序的數組,第一個數就是最小的元素。那麼剛開始只需檢測第一個數是否大於最後一個數,若小於,則直接返回第一個數就好。

 

2、考慮如下的數:

也就是說在這種情況下,當中間的數,最後一個數,第一個數都相等時,你是無法確定到底該往那邊縮小查找範圍,這種情況下只能利用O(n)級別的直接查找的方法。

故綜合上邊的討論可以寫出的最終代碼如下:

 1 #include<iostream>
 2 using namespace std;
 3 int findOrder(int elements[],int begin,int end)//特殊情況二的順序查找
 4 {
 5     int key = elements[begin];
 6     for (int i = begin; i <= end; ++i)
 7     {
 8         if (elements[i] < key)
 9             return elements[i];
10     }
11 }
12 int findInSpArray(int elements[], int length)
13 {
14     if (elements == nullptr || length <= 0)//若輸入不符合,直接返回
15         return 0;
16     int begin = 0;
17     int end = length - 1;
18     int mid = begin;//便於出現特例一時直接返回第一個數
19     while (elements[begin] >= elements[end])//每次縮小範圍後不停的檢測
20     {
21         if (end - begin == 1){//若範圍減小到兩個數,即end指向的一定是最小的數
22             mid = end;
23             break;
24         }
25         mid = (end + begin) / 2;
26         if (elements[begin] == elements[end] && elements[begin] == elements[end])//若出現特例二
27         {
28             return findOrder(elements, begin, end);
29         }
30         if (elements[begin] < elements[mid])//最小數在begin之後
31             begin = mid;
32         else if (elements[end] > elements[mid])//最小數在end之前
33             end = mid;
34     }
35     return elements[mid];//返回最小數
36 }
37 int main()
38 {
39     int a[5] = { 3, 4, 5, 1, 2 };
40     cout << findInSpArray(a, 5) << endl;
41     int b[5] = { 1, 2, 3, 4, 5 };
42     cout << findInSpArray(b, 5) << endl;
43     int c[5] = { 1, 0, 1, 1, 1 };
44     cout << findInSpArray(c, 5) << endl;
45     system("pause");
46     return 0;
47 }

 

posted @ 2016-04-20 16:06 General_up 閱讀(...) 評論(...) 編輯 收藏
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章