問題:
有一個循環有序數組A,如{7,8,9,0,1,2,3,4,5,6},不知道其最小值的位置。
那麼如何從這樣的數組中尋找一個特定的元素呢?
解決:
當然,遍歷總是一個辦法。當然面試的時候回答遍歷估計就直接杯具了。
我的想法是將原數組分段,用首元素s,中間元素m和尾元素e,可以將數組分爲兩個子數組s1,s2,
那麼,必然有至少一個子數組是有序的。那麼如何確定那一段是有序的呢?
通過分析可以看到只有3種情況:
●當s就是A中最小的元素時,以下不等式成立:
s <= m <= e
●當最小值位於(s, m]時,則有:
m <= e <= s
●當最小值出現在(m,e]時,則有:
e <= s <= m
所以通過s,m,e的大小關係,可以很輕鬆的判斷出s1和s2哪個是有序的。
通過比較要查找的目標t 與s,m,e的大小關係,可以知道t位於哪個子數組。
若t位於有序的子數組,則用二分查找就可以了。
否則,對無序的子數組重複剛纔的過程就可以了。
具體代碼如下:
#include <stdlib.h> #include <stdio.h> int binarySearch(int target, int array[], int start, int end) { int mid = -1; int l = start – 1; int r = end + 1; while(l+1 != r) { mid = l + (r – l) / 2; if(array[mid] < target) { l = mid; } else { r = mid; } } if(r <= end && array[r] == target) { return r; } else { return -1; } } int search(int target, int array[], int start, int end) { if(start > end){ return -1; } int mid = start + (end – start) / 2; int s = array[start]; int m = array[mid]; int e = array[end]; if(s <= m) { if(s <= e) { //mini value is at start return binarySearch(target, array, start, end); } else { //mini value is in range (mid, end] if(target >=s && target <= m) { return binarySearch(target, array, start, mid); } else { return search(target, array, mid+1, end); } } } else { //mini value is in range (start, mid] if(target > m && target <= e) { return binarySearch(target, array, mid + 1, end); } else { return search(target, array, start, mid); } } } int main(int argc, char* argv[]) { int t1[] = {7,8,9,0,1,2,3,4,5,6}; int i = -1; int index = -1; for(; i< 11; i++) { index = search(i, t1, 0, 9); printf(“Find %d at index %d!/n”, i, index); } return 0; }