【问题标题】:Comparing two std::vectors/arrays or in general two stl contianers比较两个 std::vectors/arrays 或一般来说两个 stl 容器
【发布时间】:2020-02-20 14:24:32
【问题描述】:

例如,我有两个字符串数组/向量

str1_arr = ["hello","my","dear","world"]
str2_arr = ["dear","my","world","hello"]

单词的位置/顺序不一样。我想知道 str1_arr 中的每个元素是否存在于 str2_arr 中,而不是真正关心它在容器中的位置。

遇到了很少的讨论herehere,但答案可以追溯到 2011 年。鉴于 c++ 已经取得了很大进展,想知道是否有更好的方法来使用 std::algorithms

谢谢

【问题讨论】:

  • 请具体一点,您的代码语法无效,解决方案取决于容器的类型
  • 也许std::is_permutation 是你所需要的。
  • @churill 您应该从该评论中做出回答。
  • @Superlokkus 为什么会这样?我无法重现这种行为。
  • @Superlokkus 对 :)

标签: c++ algorithm compare


【解决方案1】:

更新

这里有一个非修改版本和一个修改版本。艰难的排序和复制似乎需要很多工作,排序的最高复杂度是 log(n) * n,包含只有 4 * n,加上一些线性 ns,比 n^2 小很多. (用 n 近似两个范围的大小/距离,这只是较大的范围的大小)

所以对于大 O 表示法,这个解决方案是 O(n *log(n)) 而不是 O(n^2) 的天真 for 解决方案或 std::is_permutation (结果也是错误的)。

但我想知道,它仍然是复杂性的一个相当高的常数因素,所以我计算了:

即使是最坏的情况,即复制中的 2 n、排序中的 2(log(n) * n) 和包含中的 2(2n),也小于简单解决方案的 n^2,例如只有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";
}

【讨论】:

  • 是的,我正在寻找不修改范围的东西。我可以编写自己的“for loop inside a for loop”,通过每个容器中的每个元素。但我正在寻找优雅且计算有效的东西。
  • @BhanuKiran 立即查看
【解决方案2】:
std::vector<std::string> str1_arr{"hello", "my", "dear", "world"};
std::vector<std::string> str2_arr{"dear", "my", "world", "hello"};

assert(std::is_permutation(str1_arr.begin(), str1_arr.end(), 
                           str2_arr.begin(), str2_arr.end()));

根据C++ reference,如果[first1, last1) 范围内的元素存在排列使该范围等于[first2, last2) 范围,则std::is_permutation(first1, last1, first2, last2) 返回true

【讨论】:

  • ` std::vector<:string> str1_arr{"hello", "my", "dear", "world"}; std::vector<:string> str2_arr{"dear", "my", "world", "hello", "AdditionaElement"};` is_permutation 返回 false cpp.sh/7vu5z
猜你喜欢
  • 1970-01-01
  • 2010-09-17
  • 1970-01-01
  • 2011-05-25
  • 2013-12-24
  • 2021-01-04
  • 2017-11-02
相关资源
最近更新 更多