Ternary search is a divide-and-conquer search algorithm used to find the position of a target value within an increasing or decreasing function or in a unimodal array (e.g., U-shaped or ∩-shaped).
Unlike binary search, which splits the array into two parts, ternary search divides the range into three equal parts by choosing two mid-points:
- mid1 = l + (r - l) / 3
- mid2 = r - (r - l) / 3
When to use Ternary Search
- Naturally fits for unimodal arrays (e.g., strictly decreasing then increasing, or vice versa). Please refer Minimum in Decreasing Increasing Array as an example.
- To optimize a unimodal function (e.g., finding the minimum or maximum of a quadratic function).
- For problems like finding the bitonic point in a bitonic sequence.
- Evaluating a real-valued function where the function has a single local minimum or maximum.
Working of Ternary Search
Given a sorted array arr and an integer x, determine whether x is present in the array using ternary search.
Examples:
Input: arr[] = [1, 2, 3, 4, 6], x = 6
Output: true
Explanation: The element 6 is present in the array, so the output is true.
Input: arr[] = [1, 3, 4, 5, 6], x = 2
Output: false
Explanation: The element 2 is not present in the array, so the output is false.
The idea of Ternary Search is to divide the search space into three parts using two mid points. Based on the value of x, continue searching only in the possible segment. So, the Time Complexity for it O(log3 n).
#include <iostream>
#include <vector>
using namespace std;
bool ternarySearch(vector<int> &arr, int x) {
int l = 0;
int r = arr.size() - 1;
while (l <= r) {
// Split array portion into 3 parts
int mid1 = l + (r - l) / 3;
int mid2 = r - (r - l) / 3;
if (arr[mid1] == x || arr[mid2] == x) {
return true;
}
if (x < arr[mid1]) {
r = mid1 - 1;
} else if (x > arr[mid2]) {
l = mid2 + 1;
} else {
l = mid1 + 1;
r = mid2 - 1;
}
}
return false;
}
int main() {
vector<int> arr = {1, 2, 3, 4, 6};
int x = 6;
cout << (ternarySearch(arr, x) ? "true" : "false") << endl;
arr = {1, 3, 4, 5, 6};
x = 2;
cout << (ternarySearch(arr, x) ? "true" : "false") << endl;
return 0;
}
class GFG {
static boolean ternarySearch(int[] arr, int x) {
int l = 0;
int r = arr.length - 1;
while (l <= r) {
// Split array portion into 3 parts
int mid1 = l + (r - l) / 3;
int mid2 = r - (r - l) / 3;
if (arr[mid1] == x || arr[mid2] == x) {
return true;
}
if (x < arr[mid1]) {
r = mid1 - 1;
} else if (x > arr[mid2]) {
l = mid2 + 1;
} else {
l = mid1 + 1;
r = mid2 - 1;
}
}
return false;
}
public static void main(String[] args) {
int[] arr = {1, 2, 3, 4, 6};
int x = 6;
System.out.println(ternarySearch(arr, x));
arr = new int[] {1, 3, 4, 5, 6};
x = 2;
System.out.println(ternarySearch(arr, x));
}
}
def ternarySearch(arr, x):
l = 0
r = len(arr) - 1
while l <= r:
# Split array portion into 3 parts
mid1 = l + (r - l) // 3
mid2 = r - (r - l) // 3
if arr[mid1] == x or arr[mid2] == x:
return True
if x < arr[mid1]:
r = mid1 - 1
elif x > arr[mid2]:
l = mid2 + 1
else:
l = mid1 + 1
r = mid2 - 1
return False
if __name__ == "__main__":
arr = [1, 2, 3, 4, 6]
x = 6
print("true" if ternarySearch(arr, x) else "false")
arr = [1, 3, 4, 5, 6]
x = 2
print("true" if ternarySearch(arr, x) else "false")
using System;
class GFG {
static bool ternarySearch(int[] arr, int x) {
int l = 0;
int r = arr.Length - 1;
while (l <= r) {
// Split array portion into 3 parts
int mid1 = l + (r - l) / 3;
int mid2 = r - (r - l) / 3;
if (arr[mid1] == x || arr[mid2] == x) {
return true;
}
if (x < arr[mid1]) {
r = mid1 - 1;
} else if (x > arr[mid2]) {
l = mid2 + 1;
} else {
l = mid1 + 1;
r = mid2 - 1;
}
}
return false;
}
static void Main() {
int[] arr = {1, 2, 3, 4, 6};
int x = 6;
Console.WriteLine(ternarySearch(arr, x) ? "true" : "false");
arr = new int[] {1, 3, 4, 5, 6};
x = 2;
Console.WriteLine(ternarySearch(arr, x) ? "true" : "false");
}
}
function ternarySearch(arr, x) {
let l = 0;
let r = arr.length - 1;
while (l <= r) {
// Split array portion into 3 parts
let mid1 = l + Math.floor((r - l) / 3);
let mid2 = r - Math.floor((r - l) / 3);
if (arr[mid1] === x || arr[mid2] === x) {
return true;
}
if (x < arr[mid1]) {
r = mid1 - 1;
} else if (x > arr[mid2]) {
l = mid2 + 1;
} else {
l = mid1 + 1;
r = mid2 - 1;
}
}
return false;
}
// Driver Code
let arr = [1, 2, 3, 4, 6];
let x = 6;
console.log(ternarySearch(arr, x));
arr = [1, 3, 4, 5, 6];
x = 2;
console.log(ternarySearch(arr, x));
Output
true false
Difference Between Binary Search and Ternary Search
| Feature | Binary Search | Ternary Search |
|---|---|---|
| Division of Search Space | Divides the range into 2 parts | Divides the range into 3 parts |
| Mid Points Used | 1 midpoint | 2 midpoints |
| Comparisons per Iteration | Fewer comparisons | More comparisons |
| Search Space Reduced To | Half of the current range | One-third of the current range |
| Time Complexity | O(log₂ n) | O(log₃ n) |
| Practical Performance | Generally faster | Generally slower due to extra comparisons |
| Best Use Case | Searching in sorted arrays | Finding extrema in unimodal functions, or searching in sorted arrays (less common) |
| Implementation Complexity | Simpler | Slightly more complex |