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;
 
// Find the value of x in range [l, r]
// for which f(x) is minimum
// f(x) = 2*(x^2) - 10*x + 2
 
double f(double x) {
    return 2 * (x * x) - 10 * x + 2;
}
 
 
int main() {
    double l = -1e5, r = 1e5;
    // Commonly the error limit is given as
    // 1e-6 or 1e-9
    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




// Java code
 
public class MinimumValue {
    // Find the value of x in range [l, r]
    // for which f(x) is minimum
    // f(x) = 2*(x^2) - 10*x + 2
 
    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);
    }
}
 
// This code is contributed by guptapratik


Python3




# Python Code
 
# Find the value of x in the range [l, r]
# for which f(x) is minimum
# f(x) = 2*(x^2) - 10*x + 2
 
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}')
 
# This code is contributed by guptapratik


C#




// C# Code
using System;
 
class MinimumValue
{
    // Find the value of x in the range [l, r]
    // for which f(x) is minimum
    // f(x) = 2*(x^2) - 10*x + 2
 
    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}"); // Output with one decimal place
    }
}
 
// This code is contributed by guptapratik


Javascript




// Find the value of x in range [l, r]
// for which f(x) is minimum
// f(x) = 2*(x^2) - 10*x + 2
 
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; // Round to 3 decimal places
    console.log(result);
}
 
findMinimum();
 
// This code is contributed by guptapratik


Output

2.5

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.

Ternary Search for Competitive Programming

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.

Table of Content

  • What is Ternary Search?
  • Why use Ternary Search?
  • Idea behind Ternary Search
  • Use Cases of Ternary Search
  • Practice Problems on Ternary Search for Competitive Programming:

Similar Reads

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:...

Use Cases of Ternary Search:

...

Practice Problems on Ternary Search for Competitive Programming:

...