//============================================================================ // Name : SortedRotatedArray.cpp // Author : Varun Sharma // Version : 1.0 // Complexity : O(logn) // Description : Finding Element in a sorted rotated array, without finding pivot. //============================================================================ /* ALGORITHM ========= 1. Initialize start = 0, end = size-1. 2. Repeat while start <= end a. Calculate mid element => mid = (start+end)/2. b. If arr[mid] = val then print position and return true. c. Array is sorted from start to mid or from mid to end, check which one is the case. d. Sorted from Mid to end: arr[mid] < arr[end]. i. If search value lies in right sorted half : val arr[mid] && val <= arr[end] then start = mid+1 ii.Else end = mid-1 e. Else Sorted from start to mid . i. If search value lies in left sorted half: val <arr[mid] && val>= arr[start] then end = mid-1 ii.Else start = mid+1. 3. Return false if element not found. */ #include <iostream> using namespace std; bool search(int arr[],int size,int val) { int start = 0; int end = size-1; int mid; while(start <= end) { mid = (start+end)/2; //Value at mid == search value then return found. if(arr[mid] == val) { cout<<"nFOUND AT POSITION : "<<mid+1; return true; } //If value at mid < value at end //i.e. Array is sorted from mid to end. if(arr[mid] < arr[end]) { //Value lies in right sorted half of array. if(val > arr[mid] && val <= arr[end]) start = mid+1; else //Value lies in left half of array. end = mid-1; } //Array is sorted from start to mid. else { //Value lies in left sorted half of array. if(val < arr[mid] && val >= arr[start]) end = mid-1; //Value lies in right sorted half. else start = mid+1; } } return false; } int main() { int arr[] = {6,7,8,9,10,11,1,2,3,4,5}; int size = sizeof arr/sizeof arr[0]; if(!search(arr,size,6)) cout<<"nVALUE DOESN'T EXIST"; int arr1[] = {6,7,8,9,10,11,12,13,14,5}; int size1 = sizeof arr1/sizeof arr1[0]; if(!search(arr1,size1,5)) cout<<"nVALUE DOESN'T EXIST"; int arr2[] = {5,6,7,8,9,10,11,12,13,14}; int size2 = sizeof arr2/sizeof arr2[0]; if(!search(arr2,size2,5)) cout<<"nVALUE DOESN'T EXIST"; int arr3[] = {5,6,7,8,9,10,11,12,13,14}; int size3 = sizeof arr3/sizeof arr3[0]; if(!search(arr3,size3,18)) cout<<"nVALUE DOESN'T EXIST"; int arr4[] = {6,7,8,9,10,11,12,13,14,5}; int size4 = sizeof arr4/sizeof arr4[0]; if(!search(arr4,size4,1)) cout<<"nVALUE DOESN'T EXIST"; return 0; }
Monday, 8 July 2013
Given a sorted rotated array, find an element in O(logn) time without finding the pivot element.
Subscribe to:
Post Comments (Atom)
It does not work for the following array.
ReplyDelete{2,3,4,5,6,1}, Search element = 5
First iteration:
mid = 4(assuming start = 0 and end = 5).
arr[mid] < search_elem and arr[end] < search_elem,
so end = mid - 1=1;
So, search space is reduced to {0,1}, which is wrong.
Sorry for not properly tested code, btw nice catch soumya.
ReplyDeleteok, at first glance issue is:
I have assumed that pivot element will be on left of mid element so array will be sorted from mid to end (which is not true always).
We can fix this bug by checking if pivot lies in first half ( < mid) or if pivot lies in second half (>mid) it is O(1) operation.
If pivot lies in first half above code will work as array will be sorted from mid to end, but if pivot lies in second half then array will be sorted from start to mid, so instead of comparing mid element with end element compare it with start element and accordingly move end/start indexes.
I have posted the new code and algorithm.
ReplyDeleteI have tested for couple of test cases but too lazy to test it for all, please let me know in case you find any bug.
it won't work with array {2,1,0,8,7,6,5,4,3} search for 0
ReplyDeleteCharly, the array you have used as input is not in increasing order.
ReplyDeleteSorry my mistake I should have mentioned array is sorted in Increasing order and it is circular shifted from left to right.
Your array must look something like this: {3,4,5,6,7,8,0,1,2};
And code works fine for the above array.
Which mean your solution will work only on sorted array not in reverse sorted one
ReplyDeleteYes, like sorting function can sort in both ascending and descending order with little change this can be extended to work with reverse sorted array as well.
ReplyDeleteOne elegant solution could be to find the minimal number in the rotated sorted index t s.t. a[0] <= a[1] <= ...... <=a[t-1] >= a[t] and a[t] <= a[t+1]... a[n-1] and a[n-1] <= a[0] <=...<=a[t-1], this can be found in O(Log n) time with some twist of the divide and conquer. Once t is found we can do a binsearch in left and right of t and check for the target number. off course we also check if t itself is the target .
ReplyDeleteHave written the code and tested it , don't know if publishing here in comment is proper. Neways .
ReplyDelete//Find target in a rotated sorted array i.e. there exists index t s.t. a[0] <= a[1] <= ...... <=a[t-1] >= a[t] and a[t] <= a[t+1]... a[n-1] and
ReplyDelete// a[n-1] <= a[0] <=...<=a[t-1]
public static int FindTargetInRotatedSortedArray(int[] a, int target)
{
//First lets us get the index t i.e. the least element of the array note t-1th element is the max element . this would simplify things
// To do so we use the concept of bnary search divide and conquer
int low = 0, high = a.Length - 1; int mid; int t;
while(low <= high)
{
mid = (low + high) / 2;
if (a[mid] == target)
return mid;
if ((a[mid] <= a[high]) && (a[mid] <= a[low])) // indicates that mid is t i.e. the least element in the array
return FindInSplittedArray(a, target, mid); // So the target can potentially be in either of the sorted arrays 0... to t-1 or t+1 to ... n-1
else if ((a[mid] >= a[high]) && (a[mid] >= a[low])) // least element is in the right of mid
low = mid + 1;
else if ((a[mid] <= a[high]) && (a[mid] <= a[low])) // least element is in the left of mid
high = mid - 1;
else // This means a[mid ] > a[low] and a[mid] < a[high] , this is a case for normal sorted array
high = mid - 1;
}
return -2; // This means that the array is not rotated sorted as we were not able to find the least element
}
//Array a is rotated sorted array with least element at index t
private static int FindInSplittedArray(int[] a, int target, int t)
{
int result = binSearch(a, target, 0, t - 1);
if (result != -1)
return result;
return binSearch(a, target, t + 1, a.Length - 1);
}
//Array of sorted integers in the given range of low to high indices . returns index if the target is in te given range low is <= high
public static int binSearch(int[] a, int target, int low , int high)
{
if ((low < 0) || (low > a.Length - 1) || (high < 0) || (high > a.Length - 1))
return -1;
int mid;
while (low <= high)
{
mid = (low + high) / 2;
if (a[mid] == target)
return mid;
else if (a[mid ] > target)
high = mid - 1;
else
low = mid + 1;
}
return -1;