【问题标题】:Using for loop and find instead of set_intersection?使用 for 循环和查找而不是 set_intersection?
【发布时间】:2014-10-04 22:58:04
【问题描述】:

This question 建议使用std::set_intersection 来查找两个数组的交集。使用std::find 不是也可以吗?

int a[5] = {1, 2, 3, 4, 5};
int b[5] = {3, 4, 5, 6, 7};

for (int i=0; i<5; i++)
{
    if (std::find(b, b+5, a[i])!=b+5)
        std::cout << a[i] << std::endl;
}

std::set_intersection 基本上做同样的事情吗?或者它可能使用更有效的算法?如果std::find 花费 O(n) 时间,我认为上面的复杂性是 O(n^2)。

【问题讨论】:

    标签: c++ stl intersection


    【解决方案1】:

    对于所有(或至少几乎所有)标准库复杂性问题,a good reference 可以为您解答。
    特别是,我们得到 std::find 执行 At most last - first applications of the predicate(在本例中为 operator&lt;),其中 first 和 last 定义了要搜索的范围。
    我们还得到std::set_intersection 执行At most 2·(N1+N2-1) comparisons, where N1 = std::distance(first1, last1) and N2 = std::distance(first2, last2)

    这意味着您的循环最多执行 operator&lt;N1 * N2 应用程序,在本例中为 25。std::set_intersection 最多使用 18。

    因此,这两种方法“效果一样好”,因为它们给出了相同的答案,但std::set_intersection 需要更少的比较来做到这一点。

    【讨论】:

      【解决方案2】:

      std::set 是一个有序集合。此类集合有更快的方法(线性)(想想归并排序)。

      【讨论】:

        【解决方案3】:

        std::set::find 接受O(lg n),这是一个二分搜索。因此,将 for 循环与 find 一起使用需要 O(n lg n)std::set_intersection 需要线性时间:对齐两个集合以找到它们的交集(类似于mergesort的合并操作)。

        【讨论】:

        • std::find 不进行二分搜索,因为它无法先验知道输入范围已排序,因此需要线性时间。跨度>
        • 集合有自己的 find 版本。编辑指出这一点。
        • 这里没有设置对象,我们有数组。即使我们确实有集合,使用std::find 和来自集合的迭代器也不能保证采用O(log n)。只有使用std::set&lt;...&gt;::find 才能保证这样做。
        • 提到了 set_intersection 并且 OP 中的数组是排序的。链接到关于排序集的建议答案讨论。
        • std::set_intersection 不仅适用于集合,它适用于任何排序范围,其中std::set 就是一个例子。这不会改变您的std::find 只能保证花费线性时间的事实。除非你说std::find 是指std::set::find,否则你的答案有误。
        猜你喜欢
        • 1970-01-01
        • 2017-01-28
        • 1970-01-01
        • 2014-10-11
        • 2012-01-27
        • 2011-10-06
        • 2020-11-27
        • 2021-01-08
        • 1970-01-01
        相关资源
        最近更新 更多