Ternary Search for Competitive Programming
Last Updated :
22 Jan, 2024
Ternary search is a powerful algorithmic technique that plays a crucial role in competitive programming. This article explores the fundamentals of ternary search, idea behind ternary search with its use cases that will help solving complex optimization problems efficiently.
What is Ternary Search?
Ternary Search is a searching technique used to determine the minimum or maximum of a Unimodal function. Ternary Search divided the search space into three parts and then remove one of the three parts to reduce the search space.
Why use Ternary Search?
Though, the time complexity of Ternary Search (2 * log3N) is greater than Binary Search (log2N), it can be used in various places where Binary Search fails. Binary Search is used for Monotonic Functions, whereas Ternary Search is used for Unimodal Functions. It is used to find the only maxima or minima of a concave or convex function.
Note: All Binary Search Problems can be solved using Ternary Search but the reverse is not true.
Idea behind Ternary Search:
The idea behind Ternary Search is same as Binary Search but instead of dividing the search space into 2 parts and we divide it into 3 parts and remove one of them from the search space. Lets explore further with the help of an example:
Lets consider a Unimodal function f(x), such that we need to find the value of x, for which f(x) is minimum.
- Here, we take 2 mid points (lets say, mid1 and mid2) between the range [l, r] divide the Search space into three parts.
- Then calculate the value of the Unimodal function at mid1 and mid2.
- According to the values of the Unimodal function at mid1 and mid2, we can have one of the following 3 cases,
Case1: f(mid1) < f(mid2), then reduce the search space to [l, mid2]
Case 2: f(mid1) > f(mid2), then reduce the search space to [mid1, r]
Case 3: f(mid1) = f(mid2), then reduce the search space to [mid1, mid2]
- We keep on reducing the search space till we get our answer.
Similarly, we can apply ternary search to all the Unimodal Functions.
Implementation of Ternary Search:
C++
#include <bits/stdc++.h>
using namespace std;
double f( double x) {
return 2 * (x * x) - 10 * x + 2;
}
int main() {
double l = -1e5, r = 1e5;
while ((r - l) >= 1e-9) {
double mid1 = l + (r - l)/3.0;
double mid2 = r - (r - l)/3.0;
double f_mid1 = f(mid1);
double f_mid2 = f(mid2);
if (f_mid1 < f_mid2) {
r = mid2;
}
else if (f_mid1 > f_mid2) {
l = mid1;
}
else if (f_mid1 == f_mid2) {
l = mid1;
r = mid2;
}
}
cout << setprecision(9) << l << "\n" ;
return 0;
}
|
Java
public class MinimumValue {
public static double f( double x) {
return 2 * x * x - 10 * x + 2 ;
}
public static void main(String[] args) {
double l = -1e5;
double r = 1e5;
double errorLimit = 1e- 9 ;
while ((r - l) >= errorLimit) {
double mid1 = l + (r - l) / 3.0 ;
double mid2 = r - (r - l) / 3.0 ;
double f_mid1 = f(mid1);
double f_mid2 = f(mid2);
if (f_mid1 < f_mid2) {
r = mid2;
} else if (f_mid1 > f_mid2) {
l = mid1;
} else if (f_mid1 == f_mid2) {
l = mid1;
r = mid2;
}
}
System.out.printf( "%.1f\n" , l);
}
}
|
Python3
def f(x):
return 2 * x * x - 10 * x + 2
l = - 1e5
r = 1e5
error_limit = 1e - 9
while r - l > = error_limit:
mid1 = l + (r - l) / 3.0
mid2 = r - (r - l) / 3.0
f_mid1 = f(mid1)
f_mid2 = f(mid2)
if f_mid1 < f_mid2:
r = mid2
elif f_mid1 > f_mid2:
l = mid1
else :
l = mid1
r = mid2
print (f '{l:.1f}' )
|
C#
using System;
class MinimumValue
{
static double f( double x)
{
return 2 * x * x - 10 * x + 2;
}
static void Main()
{
double l = -1e5;
double r = 1e5;
double errorLimit = 1e-9;
while ((r - l) >= errorLimit)
{
double mid1 = l + (r - l) / 3.0;
double mid2 = r - (r - l) / 3.0;
double f_mid1 = f(mid1);
double f_mid2 = f(mid2);
if (f_mid1 < f_mid2)
{
r = mid2;
}
else if (f_mid1 > f_mid2)
{
l = mid1;
}
else if (f_mid1 == f_mid2)
{
l = mid1;
r = mid2;
}
}
Console.WriteLine($ "{l:f1}" );
}
}
|
Javascript
function f(x) {
return 2 * x * x - 10 * x + 2;
}
function findMinimum() {
let l = -1e5;
let r = 1e5;
const errorLimit = 1e-9;
while ((r - l) >= errorLimit) {
let mid1 = l + (r - l) / 3.0;
let mid2 = r - (r - l) / 3.0;
let f_mid1 = f(mid1);
let f_mid2 = f(mid2);
if (f_mid1 < f_mid2) {
r = mid2;
} else if (f_mid1 > f_mid2) {
l = mid1;
} else if (f_mid1 === f_mid2) {
l = mid1;
r = mid2;
}
}
const result = Math.round(l * 1000) / 1000;
console.log(result);
}
findMinimum();
|
Time Complexity: 2 * log3(N), where N is the range of [l, r]
Important Note: Instead of using the condition (r – l) >= 1e-9, we can simply maintain a counter = 0, for every iteration and break the loop after the counter reaches 300, because after reducing the search space 300 times, we will always get the answer correct up to 9 decimal places.
Use Cases of Ternary Search:
1. Evaluation of Quadratic Expressions:
Whenever we are given a quadratic function f(x) and we need to find the maxima or minima of the function, then we can simply apply ternary search to the possible range of values of x and reduce the range till we get our solution.
2. Find Bitonic Point in a Bitonic Sequence:
A Bitonic Sequence is a sequence where the numbers are arranged in strictly increasing order till a point X and all the element after X are in strictly decreasing order. Some examples of Bitonic Sequence are: [1, 2, 3, 5, 4, 3, 2, 1], [23, 45, 53, 63, 174, 335], etc. A strictly increasing or decreasing sequence is also considered as Bitonic Sequence.
3. Ternary Search on Integers:
Apart from applying ternary search on real numbers, we can also apply ternary search on integers with a slight change in the condition about when to stop the search. When we are applying ternary search on integers, we should keep searching for the answer till the difference between the low and high of the range is greater than 2, that is searching till (r – l > 2) evaluates to true.
4. Evaluation of maxima/minima of a Concave/Convex function:
Ternary Search is also used to search the maxima or minima of a concave or convex function by reducing the search space. In this type of problem, we are given a convex function f(x) and the domain of the function as [l, r], that is the function f(x) is defined for values of x lying in the range [l, r] and we need to calculate the value of x where f(x) is minimum. Similarly, we can have a concave function and calculate the value of x for which f(x) is maximum.
Practice Problems on Ternary Search for Competitive Programming:
Practice Now
|
Practice Now
|
Practice Now
|
Practice Now
|
Practice Now
|
Share your thoughts in the comments
Please Login to comment...