There are a lot of different ways of solving this problem, each has proc and cons.
Some pre-tests
- Obviously, two ranges cannot be equal, if they have different size.
- You could calculate an order independent hash function for elements in the ranges (thanks, @Michael Anderson). It could be a sum of elements, or you just could
xor
them all. Arrays with different hash value cannot be equal.
You could create an unordered_multiset
, which holds frequency of elements in the range. While it has linear complexity in average, it may be O(n^2) because of hash collisions. Quote from the Standard (N3337, § 23.5.7.2):
Complexity: Average case linear, worst case quadratic.
However, you should also remember the complexity of std::unordered_set::operator==
:
For unordered_set
and unordered_map
, the complexity of
operator==
(i.e., the number of calls to the ==
operator of the
value_type
, to the predicate returned by key_equal()
, and to the
hasher returned by hash_function()
) is proportional to N
in the
average case and to N^2
in the worst case, where N
is a.size()
.
For unordered_multiset
and unordered_multimap
, the complexity of
operator==
is 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 i
th equivalent-key group in a
.
However, if the
respective elements of each corresponding pair of equivalent-key
groups Eai
and Ebi
are arranged in the same order (as is commonly
the case, e.g., if a
and b
are unmodified copies of the same
container), then the average-case complexity for unordered_multiset
and unordered_multimap
becomes proportional to N
(but worst-case
complexity remains O(N2)
, e.g., for a pathologically bad 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 could compare sorted copies of your range. According to the Standard (N3337, § 25.4.1.1) , it has O(n * log(n))
complexity:
Complexity: 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;
}
std::all_of
with a custom predicate to find all value from one container in the other. – Persecutionlarray
as an array of five elements, but try to initialize it with six? – Persecution