upper_bound in C++

Last Updated : 19 Jan, 2026

upper_bound is a Standard Template Library (STL) function used to find the first element that is strictly greater than a given value in a sorted range. It is commonly used for efficient searching and range queries in sorted containers.

Example: Basic Usage with Vector

C++
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;

int main()
{
    vector<int> v = {10, 20, 30, 40, 50};

    // Finding upper bound for value 30 in vector v
    cout << *upper_bound(v.begin(), v.end(), 30);

    return 0;
}

Output
40

Explanation:

  • The vector is already sorted
  • upper_bound(30) skips 10, 20, 30
  • Returns iterator pointing to 40
  • Dereferencing the iterator prints 40

Syntax

iterator upper_bound(iterator first, iterator last, const T& value);

Parameters

  • first: Iterator to the first element of the range
  • last: Iterator to one past the last element of the range
  • value: The value to compare against
  • comp (optional): Custom comparison function

Return Value

  • Returns an iterator to the first element greater than value
  • Returns last if no such element exists

Note: The behavior of std::upper_bound() is undefined if the range is not sorted

The below examples demonstrate some of its common uses.

Example 1: Find Upper Bound in an Array

C++
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;

int main()
{
    int arr[5] = {10, 20, 30, 40, 50};
    int n = sizeof(arr) / sizeof(arr[0]);

    // Finding upper bound for value 30 in array arr
    cout << *upper_bound(arr, arr + n, 30);

    return 0;
}

Output
40

Explanation: This code uses upper_bound() to find and print the first element in the sorted array that is strictly greater than 30, which is 40.

Example 2: Use upper_bound() with Custom Comparator

C++
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;

bool comp(const string &a, const string &b)
{
    return lexicographical_compare(a.begin(), a.end(), b.begin(), b.end(),
                                   [](char c1, char c2) { return tolower(c1) < tolower(c2); });
}

int main()
{
    vector<string> v = {"Apple", "banana", "Cherry", "date", "Elderberry"};

    // Finding upper bound of "Avocado"
    auto ub = upper_bound(v.begin(), v.end(), "Avocado", comp);

    if (ub != v.end())
        cout << *ub;
    else
        cout << "Upper bound not found!";

    return 0;
}

Output
banana

Explanation: We need to use the custom comparator function to perform the case insensitive search as the default comparator treats the uppercase and lowercase differently.

Example 3: Check for an Element in a Sorted Vector

C++
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;

int main()
{
    vector<int> v = {10, 20, 30, 40, 50};
    int val = 40;

    // Finding the upper bound
    auto it = upper_bound(v.begin(), v.end(), val);

    // Chekcing if val exists or not
    if (it != v.begin() && *(--it) == val)
        cout << val << " is found.";
    else
        cout << val << " is NOT found.";

    return 0;
}

Output
40 is found.

Explanation: upper_bound() returns the iterator just after the matching value; to check if the value exists, decrement the iterator and compare.

Example 4: Count Elements Smaller and Larger than a Value

C++
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;

int main()
{
    vector<int> v = {10, 20, 30, 40, 50};
    int val = 30;

    // Finding the upper bound of val in v
    auto ub = upper_bound(v.begin(), v.end(), val);

    // Finding the number of smaller elements
    cout << "No. of Smaller Elements: " << ub - v.begin() << endl;

    // Finding the number of larger elements
    cout << "No. of Larger Elements: " << v.end() - ub;

    return 0;
}

Output
No. of Smaller Elements: 3
No. of Larger Elements: 2

Explanation: Counts elements based on the position returned by upper_bound().

Finding Upper Bound in a Set

It is recommended to use set::upper_bound() for set as sets do not have random access to its elements. So, the upper_bound() function have to increment it sequentially to find the middle element (part of binary search algorithm) each time leading to increased time complexity.

C++
#include <iostream>
#include <set>
#include <algorithm>
using namespace std;

int main(){
    
    set<int> s = {1, 2, 4, 4, 6, 8};

    // Recommended: O(log n)
    auto it1 = s.upper_bound(4);

    if (it1 != s.end())
        cout << "set::upper_bound -> " << *it1 << endl;
    else
        cout << "set::upper_bound -> Not found" << endl;

    // Not recommended: O(n) for set
    auto it2 = upper_bound(s.begin(), s.end(), 4);

    if (it2 != s.end())
        cout << "std::upper_bound -> " << *it2 << endl;
    else
        cout << "std::upper_bound -> Not found" << endl;

    return 0;
}

Output
set::upper_bound -> 6
std::upper_bound -> 6

Explanation:

  • set::upper_bound() uses the Red-Black Tree structure of set, giving O(log n) time complexity.
  • std::upper_bound() cannot perform binary search efficiently on set because it lacks random-access iterators, resulting in O(n) traversal.
  • Both return the same value, but performance differs significantly.


Comment