Functional specification
In a sorted array (or vector) find the longest sequences of repeated values. The size of array is expected to be relatively large (up to a million of entries).
Please see the fully functional demo.
Reservation
Just to avoid the first optimization suggestion: actual code uses my implementation of Incremental upper bound in sorted range instead of std::upper_bound
; just don't want to overcomplicate things here.
Question
Is there a way to express this in terms of C++ Standard Library algorithms using one (or a simple combination) of them to make this code more generic and avoid reinventing the wheel?
I really don’t like this code because of two loops with two passes and the ugly if-else-if, but I don’t see a way to improve it easily.
I still hope some std
algorithm or their combination could do this work much simpler.
The code
#include <algorithm>#include <iostream>#include <vector>std::pair<std::vector<size_t>,size_t> get_longest_ranges(auto first, auto last){ ptrdiff_t max_range = 0; size_t amount_of_ranges = 0; auto it = first; while (it != last) { auto it_end = std::upper_bound(it, last, *it); if (max_range == it_end - it) {++amount_of_ranges; } else if (max_range < it_end - it) { max_range = it_end - it; amount_of_ranges = 1; } it = it_end; } std::vector<size_t> ranges; ranges.reserve(amount_of_ranges); it = first; while (it != last) { auto it_end = std::upper_bound(it, last, *it); if (it_end - it == max_range) { ranges.push_back(it-first); } it = it_end; } return { ranges, max_range };}int main() { std::vector<int> v = { 1, 1, 1, 2, 2, 2, 2, 3, 3, 4, 4, 5, 6, 6, 6, 7, 7, 7, 7 }; auto [starts, length] = get_longest_ranges(v.begin(),v.end()); std::cout << "Max equal elements range length = " << length; for (auto start : starts) { std::cout << "\nAt position: " << start << " Values: "; for (size_t i = start; i < start + length; i++) { std::cout << v[i] << " "; } }}
The expected result
For the code above the expected result is:
Max equal elements range length = 4
At position: 3 Values: 2 2 2 2
At position: 15 Values: 7 7 7 7