If the array is not circular, we can use binary search to find the key. But if the array is circular we don't know where is the starting point (pivot element). Obviously we can do a linear search to find the element. But if the input array is very large the worst case performance will be very bad. We can take advantage of the fact that the array is sort and use binary search algorithm to find the element in O(N log N).
Approach:
a[0] < a[mid]
, then all values in the first half of the array are sorted. a[mid] < a[last]
, then all values in the second half of the array are sorted. - If so, binary search that half.
- If it doesn't, it must be in the unsorted half. Take that half and repeat this process
#include <iostream> #include <vector> #include <assert.h> template<typename T, typename type> int binary_search(const T& a, int left, int right, type key) { while (left <= right) { int mid = (right-left)/2 + left; // base case 1 if (a[mid] == key) return mid; // mid less than key. Move to right if (a[mid] < key) { left = mid+1; } else { right = mid-1; } } return -1; } template<typename T, typename type> int circular_search(const T& a, int left, int right, type key) { // base case 1 int mid = (right-left)/2 + left; if (a[mid] == key) return mid; // left array is sorted. if (a[0] < a[mid]) { if (key > a[left] && key < a[mid]) { return binary_search(a, left, mid-1, key); } else { return circular_search(a, mid+1, right, key); } } // right array is sorted else if (a[mid] < a[right]) { if (key > a[mid] && key < a[right]) return binary_search(a, mid+1, right, key); else return circular_search(a, left, mid-1, key); } return -1; } template<typename T> void print(const T&a) { typedef typename T::const_iterator iterator; iterator start = a.begin(); iterator end = a.end(); for(; start!=end; ++start) std::cout << *start << " "; std::cout << std::endl; } int main() { typedef std::vector<int> Input; Input temp; int n =0; // get n from user std::cin >> n; for(int i=0; i<n; ++i) { temp.push_back(i*2); } Input data; data.resize(temp.size()); // Rotate the input sequence std::rotate_copy(temp.begin(), temp.begin()+4, data1.end(), data.begin()); print(data); // get key from user int key=0; std::cin >> key; int found = circular_search<Input, int>(data, 0, n-1, key); if (found) { assert(key == data[found]); std::cout << data[found] << " found @ pos " << found << std::endl; } else std::cout << key << " not found" << std::endl; return 0; }
No comments:
Post a Comment