I need to check if a std::set
contains element/elements in a range. For example, if the set is a set<int>
{1, 2, 4, 7, 8}
, and given an int
interval [3, 5]
(inclusive with both endpoints), I need to know if it has elements in the set. In this case, return true. But if the interval is [5, 6]
, return false. The interval may be [4, 4]
, but not [5, 3]
.
Looks like I can use set::lower_bound
, but I am not sure whether this is the correct approach. I also want to keep the complexity as low as possible. I believe using lower_bound
is logarithmic, correct?
You can use lower_bound
and upper_bound
together. Your example of testing for elements between 3 and 5, inclusive, could be written as follows:
bool contains_elements_in_range = s.lower_bound(3) != s.upper_bound(5);
You can make the range inclusive or exclusive on either end by switching which function you are using (upper_bound
or lower_bound
):
s.upper_bound(2) != s.upper_bound(5); // Tests (2, 5]
s.lower_bound(3) != s.lower_bound(6); // Tests [3, 6)
s.upper_bound(2) != s.lower_bound(6); // Tests (2, 6)
Logarithmic time is the best you can achieve for this, since the set is sorted and you need to find an element in the sorted range, which requires a dichotomic search.
If you're certain that you're going to use a std::set
, then I agree that its lower_bound
method is the way to go. As you say, it will have logarithmic time complexity.
But depending what you're trying to do, your program's overall performance might be better if you use a sorted std::vector
and the standalone std::lower_bound
algorithm (std::lower_bound(v.begin(), v.end(), 3)
). This is also logarithmic, but with a lower constant. (The downside, of course, is that inserting elements into a std::vector
, and keeping it sorted, is usually much more expensive than inserting elements into a std::set
.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With