二分查找排序

  二分查找算法,是在大學階段學習的基礎性算法。算法思想簡單,但要寫出一個正確的二分查找算法並不簡單,從1946年提出,到1962年才完成一個正確的二分查找排序算法。二分查找排序算法的變種,也經常出如今各個IT公司的面試題中。本文總結資料嘗試給出一個「正確」的二分查找算法,最後給出一個二分查找排序的變種問題。面試

  1. 經典二分查找排序的算法:算法

 1 int BinarySearch(int* array, int n, int x)
 2 {
 3     assert((array != NULL) && (0 <= n));
 4 
 5     int low = 0;
 6     int high = n -1;
 7 
 8     while (low <= high)
 9     {
10         int mid = low + ((high - low) >> 1);
11         if (array[mid] == x)
12         {
13             return mid;
14         }
15         if (x > array[mid])
16         {
17             low = mid + 1;
18         }
19         else
20         {
21             high = mid -1;
22         }
23     }
24     return -1;
25 }

  可能須要關注細節問題:數組

  1)循環條件學習

  在第8行,循環的條件設置成 low <=high。若是設置成low<high,是存在問題的:當只有數組只有一個元素,而且該元素就是須要查找的元素時,算法返回錯誤的值-1,查找失敗。spa

  2)求中間元素code

  在第10行,求中間元素使用的代碼:mid = low + ((high - low) >> 1)。一些書籍中給出的是:mid = (high + low) >> 1,若是high+low很大時,會形成溢出。這種狀況出現的機率較小,可是爲了程序適應比較惡劣條件,使用第10行代碼求中間元素就顯得有必要了。blog

(ps:上面的代碼可能還存在帶完善的地方,歡迎拍磚。。。)排序

  2. 二分查找排序算法的變種it

  問題描述:已知一個有序的數組a[N],循環左移k位(k<N)後獲得新的數組b[N],在這個新的數組中查找元素x。例如:數組 a[N] = {1, 3, 5, 7, 9, 10},循環左移2位後變成數組b[N]= {5, 7, 9, 10, 1, 3},在這個新的數組上查找某個元素x。class

  上題是我在面試中問道的問題,比較慶幸的是我在《劍指offer》一書中碰到了相似的一題,書中須要找出數組b[N]最小的最小元素,所以能比較迅速的解決了這個問題。解決問題的思路和《劍指offer》提供的思路一致。

  解題思路:數組b[N]中存在着兩個部分有序的子數組,b1:{5, 7, 9, 10}和b2:{1, 3},其中b1中的元素均大於b2中的元素。在使用二分查找算法時,中間元素mid一定落入b1或者b2某個遞增序列中,具體解決步驟以下:

  Init:    low = 0, high = N-1, mid = b[low + (high - low) >> 1]

  step1: 求出數組b的中間元素mid, 若是mid == x,則返回成功,不然進入步驟step2。

  step2: if(a[low]<mid),mid落入b1數組,此時:

         1) if (a[low]<x<mid), x在有序區間[low, mid),則將high = mid -1

         2) 不然,x落入區間(mid, high],則將low = mid +1

       else mid落入b2數組,此時:

         1)if (mid< x< b[high]),x在有序區間(mid, high],則將low = mid + 1

         2)不然, x落入區間[low, mid),則將hign = mid -1

  step3: if(low <= hign) 繼續步驟step1,不然返回查找失敗

 具體的代碼以下:

 1 int rotate_array_search(int a[], int n, int x)
 2 {
 3   int low = 0;
 4   int high = n-1; 
 5   while(low <= high) 
 6   {
 7     int mid = low + ((high - low) >> 1); 
8 if(a[mid] == x) 9 return mid;
10 if(a[mid] >= a[low]) 11 { 12 if(x < a[mid] && x >= a[low]) 13 { 14 high = mid -1; 15 } 16 else 17 { 18 low = mid + 1; 19 } 20 } 21 else 22 { 23 if(x > a[mid] && x <= a[high]) 24 { 25 low = mid + 1; 26 }
     else 27 { 28 high = mid -1; 29 } 30 } 31 } 32 return -1; // 查找失敗,則返回-1 33 }
相關文章
相關標籤/搜索