0
  1. auto it = v.lower_bound(val);

  2. auto it=lower_bound(v.begin(),v.end(),val);

Question: sometimes when we use first notation given above that's works more optimally while second one gives Time Limit Exceed ...Why????

MSalters
  • 173,980
  • 10
  • 155
  • 350
  • 1
    what is `v`? Did you look up the complexity of `std::lower_bound` vs `whatever_container_you_are_using::lower_bound`? – NathanOliver Mar 15 '22 at 11:59
  • container that can provide a better version of algorithms do that via member functions and when they do their member typically has better complexity than the generic algorithm. Though this quesiton lacks too much details to be answered concisely – 463035818_is_not_an_ai Mar 15 '22 at 12:02
  • Not at all a poor question in my opinion - this is bewildering when you first encounter it. It would be useful to know the type of `v` though, to help future readers. – Bathsheba Mar 15 '22 at 12:06

2 Answers2

3

It's a common misconception that these two functions are implemented in the same way.

The C++ standard is explicit on this - for non-LegacyRandomAccessIterators, the number of comparisons is linear! std::set falls into that category, but will have a more optimised version of lower_bound specifically for it.

A good rule of thumb: always use case v.lower_bound(val); if you can.

Bathsheba
  • 231,907
  • 34
  • 361
  • 483
2

In the C++ Standard Library, many algorithms are provided as free functions. But sometimes, containers may have methods with the same name. When this is the case, the member variant is indeed the optimized variant. But that comes with a caveat: it's optimized for that container.

An example is std::sort versus std::list::sort. You can't even sort lists with std::sort, as it would be too slow. The "most optimized" choice is std::sort with std::vector. There's no special optimization needed for std::vector::sort; the free function is already fast enough.

lower_bound is similar; it too exists as a free function and a method of some containers. When your container is fixed, and that container has a lower_bound method, use that. But if you can choose your container, you need to consider all operations you need on that container.

The "Time Limit Exceeded" suggests competitive programming, where you need to know big-O complexity. C++ documents that for almost all Standard Library functions.

MSalters
  • 173,980
  • 10
  • 155
  • 350
  • It's an a*** though that template specialisation is not required (or even permitted?!) in C++ standard library implementations so (2) recovers (1) if possible. – Bathsheba Mar 15 '22 at 12:07
  • @Bathsheba: It's entirely permitted, but the problem is that the free function `std::lower_bound` can also be called on sub-ranges. (e.g. `std::next(b), std::prev(e)`) The container method implicitly has `begin, end` as arguments. – MSalters Mar 15 '22 at 12:12
  • You sure about that? My understanding is that it had to be a linear traversal for a `std::set`. – Bathsheba Mar 15 '22 at 12:16
  • @MSalters starting with C++20, you are no longer allowed to specialize standard functions: https://stackoverflow.com/questions/52760580/will-specialization-of-function-templates-in-std-for-program-defined-types-no-lo/52760860#52760860 – NathanOliver Mar 15 '22 at 12:17
  • @NathanOliver: I interpreted Bathsheba's comment as "specializations provided by the library implementer". The C++20 restriction is on specializations provided by the user. The practical problem is what happens when both the library implementer and the user try to provide specializations for the same template arguments. – MSalters Mar 15 '22 at 12:22
  • Indeed "specializations provided by the library implementer" is how I meant it to read. – Bathsheba Mar 15 '22 at 12:24