Searching Exclusive Notes
Searching Exclusive Notes
TOPICS COVERED-
▪ Linear Search
▪ Binary Search
▪ Ternary Search
▪ Binary Search Functions in C++ STL
▪ BinarySearch using Built-in Mehods in
▪ Java Sample Problems on Searching
Linear Search-
Linear Search means to sequentially traverse a given list or array and check if an
element is present in the respective array or list. The idea is to start traversing the
array and compare elements of the array one by one starting from the first element
with the given element until a match is found or end of the array is reached.
Examples :
Algorithm:
• Start from the leftmost element of arr[] and one by one compare X with each
element of arr[].
• If X matches with an element, return the index.
• If X doesn’t match with any of elements and end of the array is reached,
return -1.
Function:
// Function to linearly search the element X in the
// array arr[] of N elements
int search(int arr[], int N, int X)
{
// Pointer to traverse the array
int i;
Time Complexity: O(N). Since we are traversing the complete array, so in worst case
when the element X does not exists in the array, number of comparisons will be N.
Therefore, worst case time complexity of the linear search algorithm is O(N).
Binary Search-
Binary Search is a searching algorithm for searching an element in a sorted list or
array. Binary Search is efficient than Linear Search algorithm and performs the
search operation in logarithmic time complexity for sorted arrays or lists.
Binary Search performs the search operation by repeatedly dividing the search
interval in half. The idea is to begin with an interval covering the whole array. If the
value of the search key is less than the item in the middle of the interval, narrow the
interval to the lower half. Otherwise narrow it to the upper half. Repeatedly check
until the value is found or the interval is empty.
Problem: Given a sorted array arr[] of N elements, write a function to search a given
element X in arr[] using Binary Search Algorithm.
Algorithm: We basically ignore half of the elements just after one comparison.
Rescursion Function-
int mid = l + (r - l) / 2;
// We reach here when element is not
// present in array
// If the element is present at the
middle return -1;
// itself }
Iterative Function:
Time Complexity: O(Log N), where N is the number of elements in the array.
Ternary Search-
Ternary Search is a Divide and Conquer Algorithm used to perform search
operation in a sorted array. This algorithm is similar to the Binary Search algorithm
but rather than dividing the array into two parts, it divides the array into three equal
parts.
In this algorithm, the given array is divided into three parts and the key (element to
be searched) is compared to find the part in which it lies and that part is further
divided into three parts.
We can divide the array into three parts by taking mid1 and mid2 which can be
calculated as shown below. Initially, l and r will be equal to 0 and N-1 respectively,
where N is the length of the array.
mid1 = l + (r-l)/3
mid2 = r – (r-l)/3
Note: The array must be sorted in order to perform the Binary Search or Ternary
Search operation.
• First, we compare the key with the element at mid1. If found equal, we return
mid1.
• If not, then we compare the key with the element at mid2. If found equal, we
return mid2.
• If not, then we check whether the key is less than the element at mid1. If yes,
then recur to the first part.
• If not, then we check whether the key is greater than the element at mid2. If
yes, then recur to the third part.
• If not, then we recur to the second (middle) part.
Recursive Function-
// Recursive Function to perform Ternary }
Search
// Initially,
// Since key is not present at mid,
// l = 0, starting index of array.
// check in which region it is present
// r = N-1, ending index of array.
// then repeat the Search operation
int ternarySearch(int l, int r, int key, int ar[])
// in that region
{
if (key < ar[mid1])
if (r >= l)
{
{
if (ar[mid1] == key) {
{ }
Iterative function-
// Iterative Function to perform Ternary Search
// Initially, if (key < ar[mid1]) {
// l = 0, starting index of array.
// r = N-1, ending index of array. // The key lies in between l and mid1
int ternarySearch(int l, int r, int key, int ar[]) r = mid1 - 1;
{ }
while (r >= l) { else if (key > ar[mid2]) {
// Find mid1 and mid2 // The key lies in between mid2 and r
int mid1 = l + (r - l) / 3; l = mid2 + 1;
int mid2 = r - (r - l) / 3; }
else {
// Check if key is present at any mid
if (ar[mid1] == key) { // The key lies in between mid1 and
mid2
return mid1;
l = mid1 + 1;
}
r = mid2 - 1;
if (ar[mid2] == key) {
}
return mid2;
}
}
Time Complexity: O(Log N), where N is the number of elements in the array.
3
• binary_search()
• upper_bound()
• lower_bound()
binary_search()
This function only checks if a particular element is present in a sorted container or
not. It accepts the starting iterator, ending iterator and the element to be checked as
parameters and returns True if the element is present otherwise False.
Syntax:
Output:
15 exists in vector
20 exists in Array
Note: This function only checks if the element is present or not, it does not give any
information about the location of the element if it exists.
upper_bound()
The upper_bound() function is used to find the upper bound of an element present
in a container. That is it finds the location of an element just greater than a given
element in a container. This function accepts the start iterator, end iterator and the
element to be checked as parameters and returns the iterator pointing to the
element just greater than the element passed as the parameter. If there does not
exist any such element than the function returns an iterator pointing to the last
element.
Syntax:
Return Value: Returns an iterator pointing to the element just greater than ele.
Examples:
Input : 10 20 30 30 40 50
Output : upper_bound for element 30 will return
an iterator pointing to the element 40.
Input : 10 20 30 40 50
Output : upper_bound for element 45 will return
an iterator pointing to the element 50.
Input : 10 20 30 40 50
Output : upper_bound for element 60 will
return end iterator.
Note: We can calculate the exact index position of the elements by subtracting the
beginning iterator from the returned iterator.
#include <bits/stdc++.h>
using namespace std;
/*** USING upper_bound() WITH ARRAY
***/
// Driver code
int main() int arr[] = { 10, 20, 30, 40, 50 };
{
/*** USING upper_bound() WITH VECTOR // Print elements of array
***/
cout << "Array contains :";
for (int i = 0; i < 5; i++)
vector<int> v{ 10, 20, 30, 40, 50 };
cout << " " << arr[i];
cout << "\n";
// Print vector
cout << "Vector contains :";
// using upper_bound
for (int i = 0; i < v.size(); i++)
int up1 = upper_bound(arr, arr+5, 35) - arr;
cout << " " << v[i];
int up2 = upper_bound(arr, arr+5, 45) - arr;
cout << "\n";
Output:
Vector contains : 10 20 30 40 50
Array contains : 10 20 30 40 50
lower_bound()
The lower_bound() function is used to find the lower bound of an element present
in a container. That is it finds the location of an element just smaller than a given
element in a container. This function accepts the start iterator, end iterator and the
element to be checked as parameters and returns the iterator pointing to the lower
bound of the element passed as the parameter. If all elements of the container are
smaller are less than the element passed, then it returns the last iterator.
Syntax:
Return Value: Returns an iterator pointing to the lower bound of the element ele.
That is if ele exists in the container, it returns an iterator pointing to ele otherwise it
returns an iterator pointing to the element just greater than ele.
Below program illustrate the working of lower_bound() function with both Vectors
and Arrays:
// CPP program to illustrate lower_bound() /*** USING lower_bound() ON VECTORS
***/
// for both vectors and array
Output:
Vector contains : 10 20 30 40 50
Array contains : 10 20 30 40 50
• Arrays.binarySearch()
• Collections.binarySearch()
Arrays.binarySearch()
Arrays.binarySearch() is the simplest and most efficient method to find an element in a
sorted array in Java
Declaration:
Description: This method searches the specified array of the given data type for the
specified value using the binary search algorithm. The array must be sorted prior to making
this call. If it is not sorted, the results are undefined. If the array contains multiple elements
with the specified value, there is no guarantee which one will be found.
Parameters:
Return Value: It returns the index of the search key, if it is contained in the array; otherwise,
(-(insertion point) - 1). The insertion point is defined as the point at which the key would be
inserted into the array: the index of the first element greater than the key, or a.length if all
elements in the array are less than the specified key. Note that this guarantees that the
return value will be >= 0 if and only if the key is found.
Examples:
Searching for 35 in byteArr[] = {10,20,15,22,35}
will give result as 4 as it is the index of 35
Implementation:
// Java program to demonstrate working of Arrays.sort(floatArr);
Arrays.
Arrays.sort(shortArr);
// binarySearch() in a sorted array
Output:
35 found at index = 4
g found at index = 1
22 found at index = 3
1.5 found at index = -1
35.0 found at index = -5
5 found at index = -1
Important Points:
Collections.binarySearch()
The Collections.binarySearch() method is a Collections class method in Java that returns
position of an object in a sorted list.
Declaration:
The method throws ClassCastException if elements of list are not comparable using the
specified comparator, or the search key is not comparable with the elements.
Output :
3
-5
import java.util.List;
import java.util.ArrayList; // The last parameter specifies the
comparator method
import java.util.Collections;
// used for sorting.
int index = Collections.binarySearch(al, 50,
public class GFG
Collections.reverseOrder());
{
public static void main(String[] args)
System.out.println("Found at index " +
{ index);
List al = new ArrayList(); }
al.add(100); }
al.add(50);
Output :
Found at index 1
Input
[2, 3, 2, 1, 5]
Output
4 2
13 = 15 - x + y
x - y = 2 .... 1
P = 60
1*2*3..n = 120
60 = (120*y)/x
x = 2y .... 2
Solving Equation 1 and 2 --
x = 4 and y = 2
Note: This method can cause arithmetic overflow as we calculate product and sum of all
array elements. Can you avoid this?
2. Solution : Use Hashing We can create a auxiliary array to count the elements in the
Array. We traverse the auxiliary array for finding out missing and repeating number
in the array. Can we optimize the space ?
Pseudo Code
for (i=1 to n) {
if (count[i] == 0 )
missing = i
if (count[i] == 2 )
repeating = i
}
print(repeating, missing)
}
3. Solution : Use Negative Indexing Traverse the array. While traversing, use the
absolute value of every element as an index and make the value at this index as
negative to mark it visited. If something is already marked negative then this is the
repeating element. To find missing, traverse the array again and look for a positive
value.
Pseudo Code
Input : [1, 1, 2, 2, 2, 2, 3] , x = 2
Output : 4
Solution : Linear Search We can traverse the array and count the number of occurences of
x in the given input array.
Time Complexity : O(n)
Since Array is sorted, can we optimize the solution using binary search.
Solution: Binary Search We can solve this problem using binary search by reducing the
effective search space in each step. We will be using these steps -
1. Use Binary search to get the index of the first occurrence of x in arr[ ]. Let the index
of the first occurrence be i.
2. Use Binary search to get the index of the last occurrence of x in arr[ ]. Let the index
of the last occurrence be j.
3. Return the count as difference between first and last indices (j – i + 1);
Pseudo Code
int first_index(arr, low, high, x, n)
{
int count_occurences(arr, n, x)
{
i = first_index(arr, 0, n-1, x, n)
j = last_index(arr, 0, n-1, x, n)
count = j-i + 1
return count
}
Time Complexity : O(Log(n))
Solution :
A simple solution is to traverse the array and as soon as we find a peak element, we return
it. The worst case time complexity of this method would be O(n).Can we find a peak
element in worst time complexity better than O(n)?
We can use the Divide and Conquer. The idea is Binary Search-based, we compare the
middle element with its neighbors. If the middle element is not smaller than any of its
neighbors, then we return it. If the middle element is smaller than its left neighbor, then
there is always a peak in the left half. If the middle element is smaller than its right
neighbor, then there is always a peak in the right half (due to the same reason as left half).
Pseudo Code
Important problems-
o Search an Element in an array
o Searching an element in a sorted array
o Count 1's in binary array
o Square root of a number
o Majority Element
HIMANSHU KUMAR(LINKEDIN)
https://www.linkedin.com/in/himanshukumarmahuri
CREDITS- INTERNET.
DISCLOSURE- ALL THE DATA AND IMAGES ARE TAKEN FROM GOOGLE AND INTERNET.