 GeeksforGeeks App
Open App Browser
Continue

# Search an element in a sorted and rotated array with duplicates

Given an array arr[] which is sorted and rotated, the task is to find an element in the rotated array (with duplicates) in O(log n) time.
Note: Print the index where the key exists. In case of multiple answer print any of them

Examples:

Input: arr[] = {3, 3, 3, 1, 2, 3}, key = 3
Output:
arr = 3

Input: arr[] = {3, 3, 3, 1, 2, 3}, key = 11
Output: -1
11 is not present in the given array.

Approach: The idea is the same as the previous one without duplicates. The only difference is that due to the existence of duplicates, arr[low] == arr[mid] could be possible, the first half could be out of order (i.e. not in the ascending order, e.g. {3, 1, 2, 3, 3, 3, 3}) and we have to deal this case separately.
In that case, it is guaranteed that arr[high] also equal to arr[mid], so the condition arr[mid] == arr[low] == arr[high] can be checked before the original logic, and if so then move left and right both towards the middle by 1 and repeat.

Below is the implementation of the above approach:

## C++

 `// C++ implementation of the approach``#include ``using` `namespace` `std;` `// Function to return the index of the``// key in arr[l..h] if the key is present``// otherwise return -1``int` `search(``int` `arr[], ``int` `l, ``int` `h, ``int` `key)``{``    ``if` `(l > h)``        ``return` `-1;` `    ``int` `mid = l + (h - l) / 2;``    ``if` `(arr[mid] == key)``        ``return` `mid;` `    ``// The tricky case, just update left and right``    ``if` `((arr[l] == arr[mid])``        ``&& (arr[h] == arr[mid]))``    ``{``        ``++l;``        ``--h;``        ``return` `search(arr, l, h, key);``    ``}` `    ``// If arr[l...mid] is sorted``    ``if` `(arr[l] <= arr[mid]) {` `        ``// As this subarray is sorted, we can quickly``        ``// check if key lies in any of the halves``        ``if` `(key >= arr[l] && key <= arr[mid])``            ``return` `search(arr, l, mid - 1, key);` `        ``// If key does not lie in the first half``        ``// subarray then divide the other half``        ``// into two subarrays such that we can``        ``// quickly check if key lies in the other half``        ``return` `search(arr, mid + 1, h, key);``    ``}` `    ``// If arr[l..mid] first subarray is not sorted``    ``// then arr[mid... h] must be sorted subarray``    ``if` `(key >= arr[mid] && key <= arr[h])``        ``return` `search(arr, mid + 1, h, key);` `    ``return` `search(arr, l, mid - 1, key);``}` `// Driver code``int` `main()``{``    ``int` `arr[] = { 3, 3, 1, 2, 3, 3 };``    ``int` `n = ``sizeof``(arr) / ``sizeof``(``int``);``    ``int` `key = 3;` `    ``cout << search(arr, 0, n - 1, key);` `    ``return` `0;``}`

## Java

 `// Java implementation of the approach``class` `GFG``{``    ` `    ``// Function to return the index of the``    ``// key in arr[l..h] if the key is present``    ``// otherwise return -1``    ``static` `int` `search(``int` `arr[], ``int` `l, ``int` `h, ``int` `key)``    ``{``        ``if` `(l > h)``            ``return` `-``1``;``    ` `        ``int` `mid = l + (h - l) / ``2``;``        ``if` `(arr[mid] == key)``            ``return` `mid;``    ` `        ``// The tricky case, just update left and right``        ``if` `((arr[l] == arr[mid])``            ``&& (arr[h] == arr[mid]))``        ``{``            ``l++;``            ``h--;``              ``return` `search(arr,l,h,key);``        ``}``    ` `        ``// If arr[l...mid] is sorted``        ``else` `if` `(arr[l] <= arr[mid])``        ``{``    ` `            ``// As this subarray is sorted, we can quickly``            ``// check if key lies in any of the halves``            ``if` `(key >= arr[l] && key <= arr[mid])``                ``return` `search(arr, l, mid - ``1``, key);``    ` `            ``// If key does not lie in the first half``            ``// subarray then divide the other half``            ``// into two subarrays such that we can``            ``// quickly check if key lies in the other half``            ``else``              ``return` `search(arr, mid + ``1``, h, key);``        ``}``    ` `        ``// If arr[l..mid] first subarray is not sorted``        ``// then arr[mid... h] must be sorted subarray``           ``else`  `if` `(key >= arr[mid] && key <= arr[h])``            ``return` `search(arr, mid + ``1``, h, key);``    ` `        ``return` `search(arr, l, mid - ``1``, key);``    ``}``    ` `    ``// Driver code``    ``public` `static` `void` `main (String[] args)``    ``{``        ``int` `arr[] ={``3``, ``3``, ``1``, ``2``, ``3``, ``3``};``        ``int` `n = arr.length;``        ``int` `key = ``3``;``    ` `        ``System.out.println(search(arr, ``0``, n - ``1``, key));``    ``}``}` `// This code is contributed by AnkitRai01`

## Python3

 `# Python3 implementation of the approach` `# Function to return the index of the``# key in arr[l..h] if the key is present``# otherwise return -1``def` `search(arr, l, h, key) :` `    ``if` `(l > h) :``        ``return` `-``1``;``        ` `    ``mid ``=` `(l ``+` `h) ``/``/` `2``;``    ``if` `(arr[mid] ``=``=` `key) :``        ``return` `mid;` `    ``# The tricky case, just update left and right``    ``if` `((arr[l] ``=``=` `arr[mid]) ``and` `(arr[h] ``=``=` `arr[mid])) :``        ``l ``+``=` `1``;``        ``h ``-``=` `1``;``        ``return` `search(arr, l, h, key)``    ``# If arr[l...mid] is sorted``    ``if` `(arr[l] <``=` `arr[mid]) :` `        ``# As this subarray is sorted, we can quickly``        ``# check if key lies in any of the halves``        ``if` `(key >``=` `arr[l] ``and` `key <``=` `arr[mid]) :``            ``return` `search(arr, l, mid ``-` `1``, key);` `        ``# If key does not lie in the first half``        ``# subarray then divide the other half``        ``# into two subarrays such that we can``        ``# quickly check if key lies in the other half``        ``return` `search(arr, mid ``+` `1``, h, key);` `    ``# If arr[l..mid] first subarray is not sorted``    ``# then arr[mid... h] must be sorted subarray``    ``if` `(key >``=` `arr[mid] ``and` `key <``=` `arr[h]) :``        ``return` `search(arr, mid ``+` `1``, h, key);` `    ``return` `search(arr, l, mid ``-` `1``, key);` `# Driver code``if` `__name__ ``=``=` `"__main__"` `:` `    ``arr ``=` `[ ``3``, ``3``, ``1``, ``2``, ``3``, ``3` `];``    ``n ``=` `len``(arr);``    ``key ``=` `3``;` `    ``print``(search(arr, ``0``, n ``-` `1``, key));` `# This code is contributed by AnkitRai01`

## C#

 `// C# implementation of the approach``using` `System;` `class` `GFG``{``    ` `    ``// Function to return the index of the``    ``// key in arr[l..h] if the key is present``    ``// otherwise return -1``    ``static` `int` `search(``int` `[]arr, ``int` `l, ``int` `h, ``int` `key)``    ``{``        ``if` `(l > h)``            ``return` `-1;``    ` `        ``int` `mid = l + (h - l) / 2;``        ``if` `(arr[mid] == key)``            ``return` `mid;``    ` `        ``// The tricky case, just update left and right``        ``if` `((arr[l] == arr[mid])``            ``&& (arr[h] == arr[mid]))``        ``{``            ``++l;``            ``--h;``            ``return` `search(arr, l, h, key)``        ``}``    ` `        ``// If arr[l...mid] is sorted``        ``if` `(arr[l] <= arr[mid])``        ``{``    ` `            ``// As this subarray is sorted, we can quickly``            ``// check if key lies in any of the halves``            ``if` `(key >= arr[l] && key <= arr[mid])``                ``return` `search(arr, l, mid - 1, key);``    ` `            ``// If key does not lie in the first half``            ``// subarray then divide the other half``            ``// into two subarrays such that we can``            ``// quickly check if key lies in the other half``            ``return` `search(arr, mid + 1, h, key);``        ``}``    ` `        ``// If arr[l..mid] first subarray is not sorted``        ``// then arr[mid... h] must be sorted subarray``        ``if` `(key >= arr[mid] && key <= arr[h])``            ``return` `search(arr, mid + 1, h, key);``    ` `        ``return` `search(arr, l, mid - 1, key);``    ``}``    ` `    ``// Driver code``    ``public` `static` `void` `Main ()``    ``{``        ``int` `[]arr = { 3, 3, 1, 2, 3, 3 };``        ``int` `n = arr.Length;``        ``int` `key = 3;``    ` `        ``Console.WriteLine(search(arr, 0, n - 1, key));``    ``}``}` `// This code is contributed by AnkitRai01`

## Javascript

 ``

Output

`4`

Time Complexity: O(log N), where n represents the size of the given array. If all the elements are same, we may end up doing a linear search.
Auxiliary Space: O(logN) due to recursive stack space.

This approach is better than the recursive one as no auxiliary space is required in this case

## C++

 `// C++ implementation of the above approach using iterative``// version of binary search``#include ``using` `namespace` `std;` `int` `search(``int` `arr[], ``int` `low, ``int` `high, ``int` `key)``{` `    ``while` `(low <= high) {``        ``int` `mid = low + (high - low) / 2;` `        ``if` `(arr[mid] == key) {``            ``// if we have found our target element``            ``// return the index of target element``            ``return` `mid;``        ``}` `        ``if` `(arr[mid] == arr[low] && arr[mid] == arr[high]) {``            ``// It may happen in case of duplicates` `            ``++low;``            ``--high;``            ``continue``;``        ``}` `        ``if` `(arr[low] <= arr[mid]) {``            ``// This means array is sorted from index low to``            ``// mid We will check that if target element lies``            ``// in left half or not` `            ``if` `(key >= arr[low] && key < arr[mid])``                ``high = mid - 1;` `            ``else``                ``// This means that our target lies in other``                ``// half of array So we shift low to mid+1 to``                ``// search in right half``                ``low = mid + 1;``        ``}` `        ``else` `{``            ``// This means array is sorted between mid and``            ``// high index` `            ``// This will check our target element is``            ``// in right half or not``            ``if` `(key <= arr[high] && key > arr[mid])``                ``low = mid + 1;` `            ``else``                ``// Means our target is in left half``                ``high = mid - 1;``        ``}``    ``}` `    ``// If target element is not present` `    ``return` `-1;``}``// Driver Code``int` `main()``{``    ``int` `arr[] = { 3, 3, 1, 2, 3, 3 };``    ``int` `n = ``sizeof``(arr) / ``sizeof``(arr);` `    ``int` `key = 3;``    ``cout << search(arr, 0, n - 1, key) << endl;` `    ``return` `0;``}`

## Java

 `import` `java.util.Scanner;` `public` `class` `Main {``    ``public` `static` `int` `search(``int``[] arr, ``int` `low, ``int` `high, ``int` `key) {``        ``while` `(low <= high) {``            ``int` `mid = low + (high - low) / ``2``;` `            ``if` `(arr[mid] == key) {``                ``// if we have found our target element``                ``// return the index of target element``                ``return` `mid;``            ``}` `            ``if` `(arr[mid] == arr[low] && arr[mid] == arr[high]) {``                ``// It may happen in case of duplicates` `                ``++low;``                ``--high;``                ``continue``;``            ``}` `            ``if` `(arr[low] <= arr[mid]) {``                ``// This means array is sorted from index low to``                ``// mid We will check that if target element lies``                ``// in left half or not` `                ``if` `(key >= arr[low] && key < arr[mid])``                    ``high = mid - ``1``;` `                ``else``                    ``// This means that our target lies in other``                    ``// half of array So we shift low to mid+1 to``                    ``// search in right half``                    ``low = mid + ``1``;``            ``}` `            ``else` `{``                ``// This means array is sorted between mid and``                ``// high index` `                ``// This will check our target element is``                ``// in right half or not``                ``if` `(key <= arr[high] && key > arr[mid])``                    ``low = mid + ``1``;` `                ``else``                    ``// Means our target is in left half``                    ``high = mid - ``1``;``            ``}``        ``}` `        ``// If target element is not present` `        ``return` `-``1``;``    ``}` `    ``public` `static` `void` `main(String[] args) {``        ``int``[] arr = { ``3``, ``3``, ``1``, ``2``, ``3``, ``3` `};``        ``int` `n = arr.length;` `        ``int` `key = ``3``;``        ``System.out.println(search(arr, ``0``, n - ``1``, key));``    ``}``}`

## Python3

 `def` `search(arr, low, high, key):` `    ``while` `low <``=` `high:``        ``mid ``=` `low ``+` `(high ``-` `low) ``/``/` `2` `        ``if` `arr[mid] ``=``=` `key:``            ``# if we have found our target element``            ``# return the index of target element``            ``return` `mid` `        ``if` `arr[mid] ``=``=` `arr[low] ``and` `arr[mid] ``=``=` `arr[high]:``            ``# It may happen in case of duplicates``            ``low ``+``=` `1``            ``high ``-``=` `1``            ``continue` `        ``if` `arr[low] <``=` `arr[mid]:``            ``# This means array is sorted from index low to``            ``# mid We will check that if target element lies``            ``# in left half or not` `            ``if` `key >``=` `arr[low] ``and` `key < arr[mid]:``                ``high ``=` `mid ``-` `1``            ``else``:``                ``# This means that our target lies in other``                ``# half of array So we shift low to mid+1 to``                ``# search in right half``                ``low ``=` `mid ``+` `1` `        ``else``:``            ``# This means array is sorted between mid and``            ``# high index` `            ``# This will check our target element is``            ``# in right half or not``            ``if` `key <``=` `arr[high] ``and` `key > arr[mid]:``                ``low ``=` `mid ``+` `1``            ``else``:``                ``# Means our target is in left half``                ``high ``=` `mid ``-` `1` `    ``# If target element is not present``    ``return` `-``1` `# Driver Code``arr ``=` `[``3``, ``3``, ``1``, ``2``, ``3``, ``3``]``n ``=` `len``(arr)` `key ``=` `3``print``(search(arr, ``0``, n ``-` `1``, key))` `# This code is contributed by Prince Kumar`

## C#

 `using` `System;` `class` `MainClass {``  ``public` `static` `int` `Search(``int``[] arr, ``int` `low, ``int` `high, ``int` `key) {``    ``while` `(low <= high) {``      ``int` `mid = low + (high - low) / 2;` `      ``if` `(arr[mid] == key) {``        ``// if we have found our target element``        ``// return the index of target element``        ``return` `mid;``      ``}` `      ``if` `(arr[mid] == arr[low] && arr[mid] == arr[high]) {``        ``// It may happen in case of duplicates``        ``++low;``        ``--high;``        ``continue``;``      ``}` `      ``if` `(arr[low] <= arr[mid]) {``        ``// This means array is sorted from index low to``        ``// mid We will check that if target element lies``        ``// in left half or not``        ``if` `(key >= arr[low] && key < arr[mid])``          ``high = mid - 1;``        ``else``          ``// This means that our target lies in other``          ``// half of array So we shift low to mid+1 to``          ``// search in right half``          ``low = mid + 1;``      ``}``      ``else` `{``        ``// This means array is sorted between mid and``        ``// high index``        ``// This will check our target element is``        ``// in right half or not``        ``if` `(key <= arr[high] && key > arr[mid])``          ``low = mid + 1;``        ``else``          ``// Means our target is in left half``          ``high = mid - 1;``      ``}``    ``}` `    ``// If target element is not present``    ``return` `-1;``  ``}` `  ``public` `static` `void` `Main() {``    ``int``[] arr = { 3, 3, 1, 2, 3, 3 };``    ``int` `n = arr.Length;` `    ``int` `key = 3;``    ``Console.WriteLine(Search(arr, 0, n - 1, key));``  ``}``}`

## Javascript

 `// JavaScript implementation of the above approach` `function` `search(arr, low, high, key) {``  ``while` `(low <= high) {``    ``let mid = Math.floor(low + (high - low) / 2);` `    ``if` `(arr[mid] === key) {``      ``// if we have found our target element``      ``// return the index of target element``      ``return` `mid;``    ``}` `    ``if` `(arr[mid] === arr[low] && arr[mid] === arr[high]) {``      ``// It may happen in case of duplicates``      ``low++;``      ``high--;``      ``continue``;``    ``}` `    ``if` `(arr[low] <= arr[mid]) {``      ``// This means array is sorted from index low to``      ``// mid We will check that if target element lies``      ``// in left half or not` `      ``if` `(key >= arr[low] && key < arr[mid]) {``        ``high = mid - 1;``      ``} ``else` `{``        ``// This means that our target lies in other``        ``// half of array So we shift low to mid+1 to``        ``// search in right half``        ``low = mid + 1;``      ``}``    ``} ``else` `{``      ``// This means array is sorted between mid and``      ``// high index` `      ``// This will check our target element is``      ``// in right half or not``      ``if` `(key <= arr[high] && key > arr[mid]) {``        ``low = mid + 1;``      ``} ``else` `{``        ``// Means our target is in left half``        ``high = mid - 1;``      ``}``    ``}``  ``}` `  ``// If target element is not present` `  ``return` `-1;``}` `// Driver code``let arr = [3, 3, 1, 2, 3, 3];``let n = arr.length;` `let key = 3;``console.log(search(arr, 0, n - 1, key));`

Output

`4`

Time Complexity: O(N), where n represents the size of the given array. If all the elements are same, we may end up doing a linear search.
Auxiliary Space: O(1)

My Personal Notes arrow_drop_up