There are many ways to solve this problem, each of which has its pros and cons.
Some preliminary tests
- Obviously, two ranges cannot be equal if they have different sizes.
- You can calculate an independent hash order function for elements in ranges (thanks, @Michael Anderson). It could be the sum of the elements, or you could just
xor them all. Arrays with different hash values ββcannot be equal.
You can create an unordered_multiset that contains the frequency of the elements in a range. Although it has linear complexity on average, it can be O (n ^ 2) due to hash collisions. Quote from the standard (N3337, Β§ 23.5.7.2):
Difficulty: average random linear, worst quadratic case.
However, you should also remember the complexity of std::unordered_set::operator== :
For unordered_set and unordered_map complexity of operator== (i.e. the number of operator calls == value_type , to the predicate returned by key_equal() and to the hash returned by hash_function() ) is proportional to N in the average case and N^2 in the worst case where N is a.size() .
For unordered_multiset and unordered_multimap complexity of operator== proportional to sum of Ei^2 in the average case and to N^2 in the worst case, where N is a.size() , and Ei is the size of the ith group of equivalent keys in a .
However, if the corresponding elements of each corresponding pair of equivalent keys of the group Eai and Ebi are arranged in the same order (which is usually the case, for example, if a and b are unmodified copies of the same container), then the average size complexity for unordered_multiset and unordered_multimap becomes proportional to N ( but in the worst case, the complexity remains O(N2) , for example, for a pathologically poor hash function).
Example:
#include <iostream> #include <unordered_set> #include <vector> int main() { std::vector<int> v{5, 7, 3, 1, 2, 7}; int arr[] = {3, 5, 1, 7, 2, 7}; std::unordered_multiset<int> mv(std::begin(v), std::end(v)); std::unordered_multiset<int> ma(std::begin(arr), std::end(arr)); std::cout << "Are equal? " << (mv == ma) << std::endl; return 0; }
You can compare sorted copies of your range. According to the Standard (N3337, Β§ 25.4.1.1), it has complexity O(n * log(n)) :
Difficulty: O (N log (N)) (where N == last - first) comparisons.
Example:
#include <iostream> #include <algorithm> #include <vector> int main() { std::vector<int> v{5, 7, 3, 1, 2, 7}; int arr[] = {3, 5, 1, 7, 2, 7}; std::vector<int> sv(v); std::vector<int> sa(std::begin(arr), std::end(arr)); std::sort(std::begin(sv), std::end(sv)); std::sort(std::begin(sa), std::end(sa)); std::cout << "Are equal? " << (sv == sa) << std::endl; return 0; }