Update
Well here is a non modifying and a modifying version. Al tough sorting and copying seems like a lot of work, the highest complexity, which is of sorting is log(n) * n, and includes is just 4 * n, plus some linear ns, which is a lot less than n^2 . (Approximating the size/distance of both ranges with n, which is simply the size of the bigger one)
So for the big O notation, this solution is in O(n *log(n)) instead of O(n^2) of the naive for of for solution or std::is_permutation
(which is also wrong in the results).
But I wondered, it still a pretty high constant factor of the complexity so I calculated:
Even the worst case, which would have 2 n from copying, 2(log(n) * n) from sorting and the 2(2n) from includes, is less than the n^2, of a naive solution, for a container only of the size of 14 elements.
#include <iostream>
#include <vector>
#include <array>
#include <string>
#include <algorithm>
#include <iterator>
template<typename Iterator1, typename Iterator2>
bool is_included_general_modifying(Iterator1 begin1, Iterator1 end1, Iterator2 begin2, Iterator2 end2) {
std::sort(begin1, end1);
std::sort(begin2, end2);
return std::includes(begin2, end2, begin1, end1);
}
template<typename Iterator1, typename Iterator2>
bool is_included_general(Iterator1 begin1, Iterator1 end1, Iterator2 begin2, Iterator2 end2) {
const auto first_range_is_sorted = std::is_sorted(begin1, end1);
const auto second_range_is_sorted = std::is_sorted(begin2, end2);
if (first_range_is_sorted && second_range_is_sorted) {
return std::includes(begin2, end2, begin1, end1);
} else if (first_range_is_sorted) {
auto second_range_copy = std::vector<typename std::iterator_traits<Iterator2>::value_type>(begin2, end2);
auto new_begin2 = second_range_copy.begin(), new_end2 = second_range_copy.end();
std::sort(new_begin2, new_end2);
return std::includes(new_begin2, new_end2, begin1, end1);
} else if (second_range_is_sorted) {
auto first_range_copy = std::vector<typename std::iterator_traits<Iterator1>::value_type>(begin1, end1);
auto new_begin1 = first_range_copy.begin(), new_end1 = first_range_copy.end();
std::sort(new_begin1, new_end1);
return std::includes(begin2, end2, new_begin1, new_end1);
}
auto first_range_copy = std::vector<typename std::iterator_traits<Iterator1>::value_type>(begin1, end1);
auto new_begin1 = first_range_copy.begin(), new_end1 = first_range_copy.end();
std::sort(new_begin1, new_end1);
auto second_range_copy = std::vector<typename std::iterator_traits<Iterator2>::value_type>(begin2, end2);
auto new_begin2 = second_range_copy.begin(), new_end2 = second_range_copy.end();
std::sort(new_begin2, new_end2);
return std::includes(new_begin2, new_end2, new_begin1, new_end1);
}
int main() {
std::array<std::string, 4> str1_arr = {"hello", "my", "dear", "world"};
std::vector<std::string> str2_arr = {"additional element", "dear", "my", "world", "hello"};
std::cout << is_included_general(str1_arr.begin(), str1_arr.end(), str2_arr.begin(), str2_arr.end()) << "\n";
}