Search in a sorted and rotated Array
Last Updated :
05 Sep, 2024
Given a sorted and rotated array arr[] of n distinct elements, the task is to find the index of given key in the array. If the key is not present in the array, return -1.
Example:
Input : arr[] = {4, 5, 6, 7, 0, 1, 2}, key = 0
Output : 4
Input : arr[] = { 4, 5, 6, 7, 0, 1, 2 }, key = 3
Output : -1
Input : arr[] = {50, 10, 20, 30, 40}, key = 10
Output : 1
A simple approach is to iterate through the array and check for each element, if it matches the target then return the index. otherwise, return –1.
Complexity : O(n) time and O(1) auxiliary space
1) Find the pivot point (or index of the min element) : For example, the min in {4, 5, 6, 7, 0, 1, 2} is 0 at index 4. And the min in {50, 10, 20, 30, 40} is 10 at index 1. How to find index of min? We have discussed in detail here.
2) Do Binary Search in a Sorted Subarray: Once we find the pivot, we can easily divide the given array into two sorted subarrays using the index of the min. For example {4, 5, 6, 7, 0, 1, 2} as {{4, 5, 6, 7}, {1, 2}} and {50, 10, 20, 30, 40} as {{50}, {10, 20, 30, 40} }. Following are the cases that arise
- If the given key is same as minimum, we return
- If min index is 0, then the whole array is sorted, we call binary search for the whole array.
- Now how do we decide the subarray in other cases. One simple idea can be to call binary search for both sides. This will keep the overall time complexity as O(Log n) only, but we can save one binary search. The idea is to compare the given key with the first element. For example, {{4, 5, 6, 7}, {1, 2}} and the key = 6. If key is greater than equal to the first element, we do binary search in the first subarray else in the second.
C++
#include <bits/stdc++.h>
using namespace std;
// An iterative binary search function.
int binarySearch(vector<int> &arr, int low, int high, int x) {
while (low <= high) {
int mid = low + (high - low) / 2;
if (arr[mid] == x) return mid;
if (arr[mid] < x) low = mid + 1;
else high = mid - 1;
}
return -1;
}
// Function to get pivot. For array 3, 4, 5, 6, 1, 2
// it returns 4 (index of 1)
int findPivot(vector<int> &arr, int low, int high) {
while (low < high) {
// The current subarray is already sorted,
// the minimum is at the low index
if (arr[low] <= arr[high])
return low;
int mid = (low + high) / 2;
// The right half is not sorted. So
// the minimum element must be in the
// right half.
if (arr[mid] > arr[high])
low = mid + 1;
// The right half is sorted. Note that in
// this case, we do not change high to mid - 1
// but keep it to mid. The mid element
// itself can be the smallest
else
high = mid;
}
return low;
}
// Searches an element key in a pivoted
// sorted array arr of size n
int pivotedBinarySearch(vector<int> &arr, int n, int key) {
int pivot = findPivot(arr, 0, n - 1);
// If the minimum element is present at index
// 0, then the whole array is sorted
if (pivot == 0)
return binarySearch(arr, 0, n - 1, key);
// If we found a pivot, then first compare with pivot
// and then search in two subarrays around pivot
if (arr[pivot] == key)
return pivot;
if (arr[0] <= key)
return binarySearch(arr, 0, pivot - 1, key);
return binarySearch(arr, pivot + 1, n - 1, key);
}
// Driver program to check above functions
int main() {
// Let us search 3 in below array
vector<int> arr = {5, 6, 7, 8, 9, 10, 1, 2, 3};
int key = 3;
cout << pivotedBinarySearch(arr, arr.size(), key);
return 0;
}
Java
import java.util.Arrays;
public class Main {
// An iterative binary search function.
public static int binarySearch(int[] arr, int low, int high, int x) {
while (low <= high) {
int mid = low + (high - low) / 2;
if (arr[mid] == x) return mid;
if (arr[mid] < x) low = mid + 1;
else high = mid - 1;
}
return -1;
}
// Function to get pivot. For array 3, 4, 5, 6, 1, 2
// it returns 4 (index of 1)
public static int findPivot(int[] arr, int low, int high) {
while (low < high) {
// The current subarray is already sorted,
// the minimum is at the low index
if (arr[low] <= arr[high])
return low;
int mid = (low + high) / 2;
// The right half is not sorted. So
// the minimum element must be in the
// right half.
if (arr[mid] > arr[high])
low = mid + 1;
// The right half is sorted. Note that in
// this case, we do not change high to mid - 1
// but keep it to mid. The mid element
// itself can be the smallest
else
high = mid;
}
return low;
}
// Searches an element key in a pivoted
// sorted array arr of size n
public static int pivotedBinarySearch(int[] arr, int n, int key) {
int pivot = findPivot(arr, 0, n - 1);
// If the minimum element is present at index
// 0, then the whole array is sorted
if (pivot == 0)
return binarySearch(arr, 0, n - 1, key);
// If we found a pivot, then first compare with pivot
// and then search in two subarrays around pivot
if (arr[pivot] == key)
return pivot;
if (arr[0] <= key)
return binarySearch(arr, 0, pivot - 1, key);
return binarySearch(arr, pivot + 1, n - 1, key);
}
// Driver program to check above functions
public static void main(String[] args) {
// Let us search 3 in below array
int[] arr = {5, 6, 7, 8, 9, 10, 1, 2, 3};
int key = 3;
System.out.println(pivotedBinarySearch(arr, arr.length, key));
}
}
Python
def binary_search(arr, low, high, x):
# An iterative binary search function.
while low <= high:
mid = low + (high - low) // 2
if arr[mid] == x:
return mid
if arr[mid] < x:
low = mid + 1
else:
high = mid - 1
return -1
def find_pivot(arr, low, high):
# Function to get pivot. For array 3, 4, 5, 6, 1, 2 it returns 4 (index of 1)
while low < high:
# The current subarray is already sorted, the minimum is at the low index
if arr[low] <= arr[high]:
return low
mid = (low + high) // 2
# The right half is not sorted. So the minimum element must be in the right half.
if arr[mid] > arr[high]:
low = mid + 1
# The right half is sorted. Note that in this case, we do not change high to mid - 1
# but keep it to mid. The mid element itself can be the smallest
else:
high = mid
return low
def pivoted_binary_search(arr, n, key):
#Searches an element key in a pivoted sorted array arr of size n
pivot = find_pivot(arr, 0, n - 1)
# If the minimum element is present at index 0, then the whole array is sorted
if pivot == 0:
return binary_search(arr, 0, n - 1, key)
# If we found a pivot, then first compare with pivot and then search in two subarrays around pivot
if arr[pivot] == key:
return pivot
if arr[0] <= key:
return binary_search(arr, 0, pivot - 1, key)
return binary_search(arr, pivot + 1, n - 1, key)
# Driver program to check above functions
if __name__ == "__main__":
# Let us search 3 in below array
arr = [5, 6, 7, 8, 9, 10, 1, 2, 3]
key = 3
print(pivoted_binary_search(arr, len(arr), key))
C#
using System;
class Program {
// An iterative binary search function.
static int BinarySearch(int[] arr, int low, int high, int x) {
while (low <= high) {
int mid = low + (high - low) / 2;
if (arr[mid] == x) return mid;
if (arr[mid] < x) low = mid + 1;
else high = mid - 1;
}
return -1;
}
// Function to get pivot. For array 3, 4, 5, 6, 1, 2
// it returns 4 (index of 1)
static int FindPivot(int[] arr, int low, int high) {
while (low < high) {
// The current subarray is already sorted,
// the minimum is at the low index
if (arr[low] <= arr[high])
return low;
int mid = (low + high) / 2;
// The right half is not sorted. So
// the minimum element must be in the
// right half.
if (arr[mid] > arr[high])
low = mid + 1;
// The right half is sorted. Note that in
// this case, we do not change high to mid - 1
// but keep it to mid. The mid element
// itself can be the smallest
else
high = mid;
}
return low;
}
// Searches an element key in a pivoted
// sorted array arr of size n
static int PivotedBinarySearch(int[] arr, int n, int key) {
int pivot = FindPivot(arr, 0, n - 1);
// If the minimum element is present at index
// 0, then the whole array is sorted
if (pivot == 0)
return BinarySearch(arr, 0, n - 1, key);
// If we found a pivot, then first compare with pivot
// and then search in two subarrays around pivot
if (arr[pivot] == key)
return pivot;
if (arr[0] <= key)
return BinarySearch(arr, 0, pivot - 1, key);
return BinarySearch(arr, pivot + 1, n - 1, key);
}
// Driver program to check above functions
static void Main(string[] args) {
// Let us search 3 in below array
int[] arr = {5, 6, 7, 8, 9, 10, 1, 2, 3};
int key = 3;
Console.WriteLine(PivotedBinarySearch(arr, arr.Length, key));
}
}
JavaScript
// An iterative binary search function.
function binarySearch(arr, low, high, x) {
while (low <= high) {
let mid = low + Math.floor((high - low) / 2);
if (arr[mid] === x) return mid;
if (arr[mid] < x) low = mid + 1;
else high = mid - 1;
}
return -1;
}
// Function to get pivot. For array 3, 4, 5, 6, 1, 2
// it returns 4 (index of 1)
function findPivot(arr, low, high) {
while (low < high) {
// The current subarray is already sorted,
// the minimum is at the low index
if (arr[low] <= arr[high])
return low;
let mid = Math.floor((low + high) / 2);
// The right half is not sorted. So
// the minimum element must be in the
// right half.
if (arr[mid] > arr[high])
low = mid + 1;
// The right half is sorted. Note that in
// this case, we do not change high to mid - 1
// but keep it to mid. The mid element
// itself can be the smallest
else
high = mid;
}
return low;
}
// Searches an element key in a pivoted
// sorted array arr of size n
function pivotedBinarySearch(arr, n, key) {
let pivot = findPivot(arr, 0, n - 1);
// If the minimum element is present at index
// 0, then the whole array is sorted
if (pivot === 0)
return binarySearch(arr, 0, n - 1, key);
// If we found a pivot, then first compare with pivot
// and then search in two subarrays around pivot
if (arr[pivot] === key)
return pivot;
if (arr[0] <= key)
return binarySearch(arr, 0, pivot - 1, key);
return binarySearch(arr, pivot + 1, n - 1, key);
}
// Driver program to check above functions
function main() {
// Let us search 3 in below array
const arr = [5, 6, 7, 8, 9, 10, 1, 2, 3];
const key = 3;
console.log(pivotedBinarySearch(arr, arr.length, key));
}
main();
Using One Binary Search:
The idea is based on the fact that in a sorted and rotated array, if we go to mid, then either the left half would be sorted or the right half (Both can also be sorted if the mid is the minimum or maximum element). For example, n arr[] = {5, 6, 0, 1, 2, 3, 4}, mid = 3 and we can see that the subarray from mid+1 to high is sorted. And in {5, 6, 7, 8, 9, 3, 4}, we can see that the subarray from low to mid-1 is sorted. We can check which half is sorted by comparing arr[low] and arr[mid] (We could also compare arr[high] and arr[mid]).
- Find the mid point. If key is same as the mid, return the mid.
- Find which half is sorted. If the key lies in the sorted half, move to that half. Otherwise move to the other half.
Note that once we find which half is sorted, we can easily check if the key lies here by checking if key lies in the range from smallest to largest in this half.
C++
#include <bits/stdc++.h>
using namespace std;
int pivotedSearch(vector<int>& arr, int key) {
// Initialize two pointers, low and high, at the start
// and end of the array.
int low = 0, high = arr.size() - 1;
while (low <= high) {
int mid = low + (high - low) / 2;
// Case 1: Find key
if (arr[mid] == key)
return mid;
// Case 2: Left half is sorted
if (arr[mid] >= arr[low]) {
// If the key lies within this sorted half,
// move the high pointer to mid - 1.
if (key >= arr[low] && key < arr[mid])
high = mid - 1;
// Otherwise, move the low pointer to mid + 1.
else
low = mid + 1;
}
// Case 3: Right half is sorted
else {
// If the key lies within this sorted half,
// move the low pointer to mid + 1.
if (key > arr[mid] && key <= arr[high])
low = mid + 1;
// Otherwise, move the high pointer to mid - 1.
else
high = mid - 1;
}
}
return -1; // Key not found
}
// Driver code
int main() {
vector<int> arr1 = {4, 5, 6, 7, 0, 1, 2};
int key1 = 0;
int result1 = pivotedSearch(arr1, key1);
cout << result1 << endl; // Output: 4
vector<int> arr2 = {4, 5, 6, 7, 0, 1, 2};
int key2 = 3;
int result2 = pivotedSearch(arr2, key2);
cout << result2 << endl; // Output: -1
return 0;
}
Java
import java.util.*;
public class GFG {
// Search in a pivoted sorted array
public static int pivotedSearch(List<Integer> arr, int key) {
int low = 0, high = arr.size() - 1;
while (low <= high) {
int mid = low + (high - low) / 2;
// Case 1: Find key
if (arr.get(mid) == key)
return mid;
// Case 2: Left half is sorted
if (arr.get(mid) >= arr.get(low)) {
if (key >= arr.get(low) && key < arr.get(mid))
high = mid - 1;
else
low = mid + 1;
}
// Case 3: Right half is sorted
else {
if (key > arr.get(mid) && key <= arr.get(high))
low = mid + 1;
else
high = mid - 1;
}
}
return -1; // Key not found
}
public static void main(String[] args) {
List<Integer> arr1 = Arrays.asList(4, 5, 6, 7, 0, 1, 2);
int key1 = 0;
int result1 = pivotedSearch(arr1, key1);
System.out.println(result1); // Output: 4
List<Integer> arr2 = Arrays.asList(4, 5, 6, 7, 0, 1, 2);
int key2 = 3;
int result2 = pivotedSearch(arr2, key2);
System.out.println(result2); // Output: -1
}
}
Python
def pivoted_search(arr, key):
low, high = 0, len(arr) - 1
while low <= high:
mid = low + (high - low) // 2
# Case 1: Find key
if arr[mid] == key:
return mid
# Case 2: Left half is sorted
if arr[mid] >= arr[low]:
if key >= arr[low] and key < arr[mid]:
high = mid - 1
else:
low = mid + 1
# Case 3: Right half is sorted
else:
if key > arr[mid] and key <= arr[high]:
low = mid + 1
else:
high = mid - 1
return -1 # Key not found
# Driver code
arr1 = [4, 5, 6, 7, 0, 1, 2]
key1 = 0
result1 = pivoted_search(arr1, key1)
print(result1) # Output: 4
arr2 = [4, 5, 6, 7, 0, 1, 2]
key2 = 3
result2 = pivoted_search(arr2, key2)
print(result2) # Output: -1
C#
using System;
using System.Collections.Generic;
public class GFG {
// Search in a pivoted sorted array
public static int PivotedSearch(List<int> arr, int key) {
int low = 0, high = arr.Count - 1;
while (low <= high) {
int mid = low + (high - low) / 2;
// Case 1: Find key
if (arr[mid] == key)
return mid;
// Case 2: Left half is sorted
if (arr[mid] >= arr[low]) {
if (key >= arr[low] && key < arr[mid])
high = mid - 1;
else
low = mid + 1;
}
// Case 3: Right half is sorted
else {
if (key > arr[mid] && key <= arr[high])
low = mid + 1;
else
high = mid - 1;
}
}
return -1; // Key not found
}
public static void Main() {
List<int> arr1 = new List<int> { 4, 5, 6, 7, 0, 1, 2 };
int key1 = 0;
int result1 = PivotedSearch(arr1, key1);
Console.WriteLine(result1); // Output: 4
List<int> arr2 = new List<int> { 4, 5, 6, 7, 0, 1, 2 };
int key2 = 3;
int result2 = PivotedSearch(arr2, key2);
Console.WriteLine(result2); // Output: -1
}
}
JavaScript
function pivotedSearch(arr, key) {
let low = 0, high = arr.length - 1;
while (low <= high) {
let mid = low + Math.floor((high - low) / 2);
// Case 1: Find key
if (arr[mid] === key) {
return mid;
}
// Case 2: Left half is sorted
if (arr[mid] >= arr[low]) {
if (key >= arr[low] && key < arr[mid]) {
high = mid - 1;
} else {
low = mid + 1;
}
}
// Case 3: Right half is sorted
else {
if (key > arr[mid] && key <= arr[high]) {
low = mid + 1;
} else {
high = mid - 1;
}
}
}
return -1; // Key not found
}
// Driver code
const arr1 = [4, 5, 6, 7, 0, 1, 2];
const key1 = 0;
const result1 = pivotedSearch(arr1, key1);
console.log(result1); // Output: 4
const arr2 = [4, 5, 6, 7, 0, 1, 2];
const key2 = 3;
const result2 = pivotedSearch(arr2, key2);
console.log(result2); // Output: -1
Time Complexity: O(log n)
Auxiliary Space: O(1)
Please Login to comment...