Open In App

Find an element in Bitonic array

Improve
Improve
Like Article
Like
Save
Share
Report

Given a bitonic sequence of n distinct elements, and an integer x, the task is to write a program to find given element x in the bitonic sequence in O(log n) time. 

A Bitonic Sequence is a sequence of numbers that is first strictly increasing then after a point decreasing.

Examples: 

Input :  arr[] = {-3, 9, 18, 20, 17, 5, 1}, key = 20
Output : Found at index 3

Input :  arr[] = {5, 6, 7, 8, 9, 10, 3, 2, 1}, key = 30
Output : Not Found

Naive Approach: A simple solution is to do a linear search. The time complexity of this solution would be O(n).

Efficient Approach: An efficient solution is based on Binary Search

  • The idea is to find the bitonic point ‘k’ which is the index of the maximum element of a given sequence. 
  • If the element to be searched is greater than the maximum element return -1, 
  • else search the element in both halves

Below is the step by step algorithm on how to do this.

  1. Find the bitonic point in the given array, i.e the maximum element in the given bitonic array. This can be done in log(n) time by modifying the binary search algorithm. You can refer to this post on how to do this.
  2. If the element to be searched is equal to the element at the bitonic point then print the index of the bitonic point.
  3. If the element to be searched is greater than the element at a bitonic point then the element does not exist in the array.
  4. If the element to be searched is less than the element at a bitonic point then search for the element in both halves of the array using binary search.

Below is the implementation of the above idea: 

C++




// C++ code to search key in bitonic array
#include <iostream>
 
using namespace std;
 
// Function for binary search in ascending part
int ascendingBinarySearch(int arr[], int low,
                        int high, int key)
{
    while (low <= high)
    {
        int mid = low + (high - low) / 2;
        if (arr[mid] == key)
            return mid;
        if (arr[mid] > key)
            high = mid - 1;
        else
            low = mid + 1;
    }
    return -1;
}
 
// Function for binary search in
// descending part of array
int descendingBinarySearch(int arr[], int low,
                        int high, int key)
{
    while (low <= high)
    {
        int mid = low + (high - low) / 2;
        if (arr[mid] == key)
            return mid;
        if (arr[mid] < key)
            high = mid - 1;
        else
            low = mid + 1;
    }
    return -1;
}
 
// finding bitonic point
int findBitonicPoint(int arr[], int n,
                    int l, int r)
{
    int mid;
    int bitonicPoint = 0;
    mid = (r + l) / 2;
    if (arr[mid] > arr[mid - 1]
        && arr[mid] > arr[mid + 1])
    {
        return mid;
    }
 
    else if (arr[mid] > arr[mid - 1]
            && arr[mid] < arr[mid + 1])
    {
        bitonicPoint = findBitonicPoint(arr, n, mid, r);
    }
 
    else if (arr[mid] < arr[mid - 1]
            && arr[mid] > arr[mid + 1])
    {
        bitonicPoint = findBitonicPoint(arr, n, l, mid);
    }
    return bitonicPoint;
}
 
// Function to search key in
// bitonic array
int searchBitonic(int arr[], int n,
                int key, int index)
{
    if (key > arr[index])
        return -1;
 
    else if (key == arr[index])
        return index;
 
    else {
        int temp
            = ascendingBinarySearch(arr,
                                    0, index - 1,
                                    key);
        if (temp != -1) {
            return temp;
        }
 
        // Search in right of k
        return descendingBinarySearch(arr,
                                    index + 1,
                                    n - 1,
                                    key);
    }
}
 
// Driver code
int main()
{
    int arr[] = { -8, 1, 2, 3, 4, 5, -2, -3 };
    int key = 1;
    int n, l, r;
    n = sizeof(arr) / sizeof(arr[0]);
    l = 0;
    r = n - 1;
    int index;
 
    // Function call
    index = findBitonicPoint(arr, n, l, r);
 
    int x = searchBitonic(arr, n, key, index);
 
    if (x == -1)
        cout << "Element Not Found" << endl;
    else
        cout << "Element Found at index " << x << endl;
 
    return 0;
}


Java




// Java code to search key in bitonic array
public class GFG {
 
    // Function for binary search
    // in ascending part
    static int ascendingBinarySearch(int arr[],
                                    int low,
                                    int high,
                                    int key)
    {
        while (low <= high)
        {
            int mid = low + (high - low) / 2;
            if (arr[mid] == key)
            {
                return mid;
            }
            if (arr[mid] > key)
            {
                high = mid - 1;
            }
            else
            {
                low = mid + 1;
            }
        }
        return -1;
    }
 
    // Function for binary search in
    // descending part of array
    static int descendingBinarySearch(int arr[],
                                    int low,
                                    int high,
                                    int key)
    {
        while (low <= high)
        {
            int mid = low + (high - low) / 2;
            if (arr[mid] == key)
            {
                return mid;
            }
            if (arr[mid] < key)
            {
                high = mid - 1;
            }
            else
            {
                low = mid + 1;
            }
        }
        return -1;
    }
 
    // finding bitonic point
    static int findBitonicPoint(int arr[],
                                int n,
                                int l,
                                int r)
    {
        int mid;
        int bitonicPoint = 0;
        mid = (r + l) / 2;
        if (arr[mid] > arr[mid - 1]
            && arr[mid] > arr[mid + 1])
        {
            return mid;
        }
        else {
            if (arr[mid] > arr[mid - 1]
                && arr[mid] < arr[mid + 1])
            {
                bitonicPoint = findBitonicPoint(arr, n, mid, r);
            }
            else {
                if (arr[mid] < arr[mid - 1]
                    && arr[mid] > arr[mid + 1])
                {
                    bitonicPoint = findBitonicPoint(arr, n, l, mid);
                }
            }
        }
        return bitonicPoint;
    }
 
    // Function to search key in bitonic array
    static int searchBitonic(int arr[], int n,
                            int key, int index)
    {
        if (key > arr[index])
        {
            return -1;
        }
        else if (key == arr[index])
        {
            return index;
        }
        else {
            int temp = ascendingBinarySearch(
                arr, 0, index - 1, key);
            if (temp != -1)
            {
                return temp;
            }
 
            // Search in right of k
            return descendingBinarySearch(arr, index + 1,
                                        n - 1, key);
        }
    }
 
    // Driver code
    public static void main(String args[])
    {
        int arr[] = { -8, 1, 2, 3, 4, 5, -2, -3 };
        int key = 5;
        int n, l, r;
        n = arr.length;
        l = 0;
        r = n - 1;
        int index;
        index = findBitonicPoint(arr, n, l, r);
 
        int x = searchBitonic(arr, n, key, index);
 
        if (x == -1) {
            System.out.println("Element Not Found");
        }
        else {
            System.out.println("Element Found at index "
                            + x);
        }
    }
}
 
/*This code is contributed by 29AjayKumar*/


Python3




# Python code to search key in bitonic array
 
# Function for binary search in ascending part
def ascendingBinarySearch(arr, low, high, key):
     
    while low <= high:
        mid = low + (high - low) // 2
         
        if arr[mid] == key:
            return mid
         
        if arr[mid] > key:
            high = mid - 1
        else:
            low = mid + 1
             
    return -1
 
# Function for binary search in descending part of array
def descendingBinarySearch(arr, low, high, key):
     
    while low <= high:
        mid = low + (high - low) // 2
         
        if arr[mid] == key:
            return mid
         
        if arr[mid] < key:
            high = mid - 1
        else:
            low = mid + 1
             
    return -1
 
# Find bitonic point
def findBitonicPoint(arr, n, l, r):
     
    bitonicPoint = 0
    mid = (r + l) // 2
     
    if arr[mid] > arr[mid-1] and arr[mid] > arr[mid+1]:
        return mid
     
    elif arr[mid] > arr[mid-1] and arr[mid] < arr[mid+1]:
        bitonicPoint = findBitonicPoint(arr, n, mid, r)
    else:
        bitonicPoint = finsBitonicPoint(arr, n, l, mid)
         
    return bitonicPoint
 
# Function to search key in bitonic array
def searchBitonic(arr, n, key, index):
     
    if key > arr[index]:
        return -1
    elif key == arr[index]:
        return index
    else:
        temp = ascendingBinarySearch(arr, 0, index-1, key)
        if temp != -1:
            return temp
         
        # search in right of k
        return descendingBinarySearch(arr, index+1, n-1, key)
     
# Driver code
def main():
    arr = [-8, 1, 2, 3, 4, 5, -2, -3]
    key = 1
    n = len(arr)
    l = 0
    r = n - 1
     
    # Function call
    index = findBitonicPoint(arr, n, l, r)
     
    x = searchBitonic(arr, n, key, index)
     
    if x == -1:
        print("Element Not Found")
    else:
        print("Element Found at index", x)
         
main()
 
# This code is contributed by stutipathak31jan


C#




// C# code to search key in bitonic array
using System;
 
class GFG {
    // Function for binary search in ascending part
    static int ascendingBinarySearch(int[] arr, int low,
                                    int high, int key)
    {
        while (low <= high)
        {
            int mid = low + (high - low) / 2;
            if (arr[mid] == key)
            {
                return mid;
            }
            if (arr[mid] > key)
            {
                high = mid - 1;
            }
            else {
                low = mid + 1;
            }
        }
        return -1;
    }
 
    // Function for binary search in descending part of
    // array
    static int descendingBinarySearch(int[] arr, int low,
                                    int high, int key)
    {
        while (low <= high)
        {
            int mid = low + (high - low) / 2;
            if (arr[mid] == key)
            {
                return mid;
            }
            if (arr[mid] < key)
            {
                high = mid - 1;
            }
            else
            {
                low = mid + 1;
            }
        }
        return -1;
    }
 
    // finding bitonic point
    static int findBitonicPoint(int[] arr, int n, int l,
                                int r)
    {
        int mid;
        int bitonicPoint = 0;
        mid = (r + l) / 2;
        if (arr[mid] > arr[mid - 1]
            && arr[mid] > arr[mid + 1])
        {
            return mid;
        }
        else
        {
            if (arr[mid] > arr[mid - 1]
                && arr[mid] < arr[mid + 1]) {
                bitonicPoint = findBitonicPoint(arr, n, mid, r);
            }
            else
            {
                if (arr[mid] < arr[mid - 1]
                    && arr[mid] > arr[mid + 1]) {
                    bitonicPoint = findBitonicPoint(arr, n, l, mid);
                }
            }
        }
        return bitonicPoint;
    }
 
    // Function to search key in bitonic array
    static int searchBitonic(int[] arr, int n, int key,
                            int index)
    {
        if (key > arr[index])
        {
            return -1;
        }
        else if (key == arr[index])
        {
            return index;
        }
        else {
            int temp = ascendingBinarySearch(
                arr, 0, index - 1, key);
            if (temp != -1) {
                return temp;
            }
 
            // Search in right of k
            return descendingBinarySearch(arr, index + 1,
                                        n - 1, key);
        }
    }
 
    // Driver Code
    static public void Main()
    {
        int[] arr = { -8, 1, 2, 3, 4, 5, -2, -3 };
        int key = 1;
        int n, l, r;
        n = arr.Length;
        l = 0;
        r = n - 1;
        int index;
        index = findBitonicPoint(arr, n, l, r);
 
        int x = searchBitonic(arr, n, key, index);
 
        if (x == -1) {
            Console.WriteLine("Element Not Found");
        }
        else {
            Console.WriteLine("Element Found at index "
                            + x);
        }
    }
}
 
// This code is contributed by ajit


Javascript




<script>
 
// JavaScript code to search key in bitonic array
 
 
// Function for binary search in ascending part
function ascendingBinarySearch(arr, low, high, key) {
    while (low <= high) {
        let mid = Math.floor(low + (high - low) / 2);
        if (arr[mid] == key)
            return mid;
        if (arr[mid] > key)
            high = mid - 1;
        else
            low = mid + 1;
    }
    return -1;
}
 
// Function for binary search in
// descending part of array
function descendingBinarySearch(arr, low, high, key) {
    while (low <= high) {
        let mid = Math.floor(low + (high - low) / 2);
        if (arr[mid] == key)
            return mid;
        if (arr[mid] < key)
            high = mid - 1;
        else
            low = mid + 1;
    }
    return -1;
}
 
// finding bitonic point
function findBitonicPoint(arr, n, l, r) {
    let mid;
    let bitonicPoint = 0;
    mid = Math.floor((r + l) / 2);
    if (arr[mid] > arr[mid - 1]
        && arr[mid] > arr[mid + 1]) {
        return mid;
    }
 
    else if (arr[mid] > arr[mid - 1]
        && arr[mid] < arr[mid + 1]) {
        bitonicPoint = findBitonicPoint(arr, n, mid, r);
    }
 
    else if (arr[mid] < arr[mid - 1]
        && arr[mid] > arr[mid + 1]) {
        bitonicPoint = findBitonicPoint(arr, n, l, mid);
    }
    return bitonicPoint;
}
 
// Function to search key in
// bitonic array
function searchBitonic(arr, n, key, index) {
    if (key > arr[index])
        return -1;
 
    else if (key == arr[index])
        return index;
 
    else {
        let temp
            = ascendingBinarySearch(arr,
                0, index - 1,
                key);
        if (temp != -1) {
            return temp;
        }
 
        // Search in right of k
        return descendingBinarySearch(arr,
            index + 1,
            n - 1,
            key);
    }
}
 
// Driver code
 
let arr = [-8, 1, 2, 3, 4, 5, -2, -3];
let key = 1;
let n, l, r;
n = arr.length;
l = 0;
r = n - 1;
let index;
 
// Function call
index = findBitonicPoint(arr, n, l, r);
 
let x = searchBitonic(arr, n, key, index);
 
if (x == -1)
    document.write("Element Not Found" + "<br>");
else
    document.write("Element Found at index " + x + "<br>");
     
</script>


Output

Element Found at index 1

Time complexity: O(log n) 
Auxiliary Space: O(1)



Last Updated : 14 Jul, 2022
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads