确定一个向量是否是另一个向量的子集的有效方法?

时间:2016-03-30 20:33:41

标签: c++ c++11 vector

给定两个排序的向量,包括介于0和一些已知的&n;之间的唯一值。并且一个向量(set1)的大小总是大于候选向量set2的大小。

查询:是否确定给定的set2是否是set1的子集?

除了C ++ 11中的以下实现之外,它们是否有更好,更有效的方法?

#include <iostream>
#include <vector>


bool subSetCheck(std::vector<int> set1, std::vector<int> set2) {

    //Set1 & 2 are always sorted and contain only unique integers from 0 to some known 'n'
    //Set1 is always larger than Set2 in size

    std::vector<int>::iterator it1 = set1.begin();
    std::vector<int>::iterator it2 = set2.begin();
    bool subSet = true;
    for (; (it1 != set1.end()) && (it2 !=set2.end()) ;) {

        if ( *it1 == *it2) {++it1; ++it2;}
        else if( *it1 > *it2) ++it2;
        else ++it1;
    }

    if (it1 ==set1.end()) subSet = false;

    return subSet;
}

int main () {

    std::vector<int> set1{0,1,2,3,4};
    std::vector<int> set2{0,1,5};

    if (subSetCheck(set1,set2)) std::cout << "Yes, set2 is subset of set1." << std::endl;
    else std::cout << "No! set2 is not a subset of set1." << std::endl;

    return 0;
}

2 个答案:

答案 0 :(得分:5)

您可以使用std::includes

std::vector<int> a{1,2,3,4,5};
std::vector<int> b{1,2,6};
std::cout << std::includes(a.begin(), a.end(), b.begin(), b.end()) << std::endl;

答案 1 :(得分:0)

是的,有更有效的方法。你的问题的答案取决于你是否在大多数情况下假设,矢量将是一个子集,或者不是。

这都是假设没有重复的元素。

让我们这样看待它。如果vec2恰好是vec1的一个子集,那么验证将采用O(vec1.size()),因为你必须查看每个元素。

在这种情况下,您的实施已经非常接近最优。您可以通过使用二进制搜索来查找vec1中的第一个匹配元素,而不是像现在一样进行线性搜索。

一旦你找到了这个元素,你就无法做其他事情而不是遍历所有元素并进行比较。

另一方面,如果你假设set2的大部分时间而不是是set1的嫌疑人,你应该采用不同的方法。

开头是一样的:使用二进制搜索在set1中找到set2的第一个元素。

然后,使用二进制搜索在set1中查找set2的最后一个元素。

然后,检查范围的大小是否与set2的大小匹配。如果没有,你现在可以拯救。

最后,如果大小匹配,请逐个元素进行比较。

如果你有重复的元素,事情变得棘手,并且弄清楚如何做到这一点留给读者做练习。