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

Efficient way of determining whether one vector is a subset of another or not?

本文关键字:向量 是否是 另一个 子集 方法 有效 一个      更新时间:2023-10-16

给定两个排序向量,它们由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;
}

您可以使用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;

是的,有更有效的方法。你的问题的答案取决于你是否假设在大多数时候,向量将是一个子集。

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

让我们这样看吧。如果vec2恰好是vec1的子集,那么验证它需要O(vec1.size()),因为您必须查看每个元素。

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

一旦找到了元素,除了迭代所有元素并进行比较之外,您真的没有什么可做的了。

另一方面,如果您假设set2的大部分时间是而不是的set1的susbet,那么您应该采用不同的方法。

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

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

然后,检查跨度的大小是否与set2的大小匹配。如果没有,你现在就可以保释。

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

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