快速矢量元素比较

Fast vector element comparison

本文关键字:元素 比较      更新时间:2023-10-16

我想比较填充整数的向量的元素,看看是否对于具有相同值的元素(并计算它们(。

例如,如果a[i]==x,是否有b[j]==x

想到的第一个实现当然是最简单的实现:

for (int i=0; i < a.size(); i++) {
  for (int j=0; j < b.size(); j++) {
    if (a[i]==b[j]) {counter++;}
  }

对于较大的矢量,这是减慢速度的方法。我想过一个交替算法,但我不熟练地实现没错,所以这就是我所拥有的和我的问题:

  for (int i = 0; i < n; i++) {
    for (int j = 0; j < m; j++) {
      if (b[j] >= a[i]) {
        counter++;
        for (int k = i + 1; k < n; k++) {
          if (a[k] >= b[j+1]) {
            counter++;
            for (int l = k + 1; l < m; l++) {
              if (b[l] >= a[k]) {
                counter++;
                ....
              }
            }
          }
        }
      }
    }
  }

流程是我开始将a的第一个元素与b元素进行比较。当我命中时,我会跳到向量b,并将其下一个元素与我之前比较的a元素之后的a元素进行比较。(由于 ab 的元素是按升序存储的,一旦我正在比较的b元素大于我在>= 上更改向量的元素a而不是 ==(

我认为,对于调用自己的函数来说,这应该很容易做到。但我无法绕开它。

我希望有人能理解我想做什么,但我现在无法更好地解释它。从理论上讲,我认为对于升序向量来说,这应该更快,因为您只需要进行 N 比较(N 是较大向量的大小(而不是 N*M .

这是合并两个排序向量的经典问题的变体。

如果向量

已排序,您需要做的就是对向量b中向量a的顺序元素执行增量线性搜索。b中的每个搜索都从上一个搜索停止的地方开始。这种方法将进行O(a.size() + b.size())比较。

int count = 0;
int j = 0;
for (int i = 0; i < a.size(); ++i)
  for (; j < b.size() && b[j] <= a[i]; ++j)
    if (b[j] == a[i])
      ++count;

如果你仔细观察,你会发现这与@Anedar的答案完全相同,只是从"不同的有利位置"表达。

但是,如果这两个向量的长度明显不同(例如,ab短得多(,那么取a的顺序元素并在b中进行二叉搜索可能是有意义的。同样,b中的每个搜索都从先前找到的 b 元素"向右"工作。这种方法将进行O(a.size() * log b.size())比较。

如果a.size() ~ b.size()那么O(a.size() + b.size())O(a.size() * log b.size())好。但如果a.size() << b.size(),那就反过来了。

既然你说元素是按顺序存储的,你可以做这样的事情:

int i=0;
int j=0;
while(i< a.size() && j<b.size()){
  if(a[i]==b[j]){
    ++counter;
    ++i;
    ++j;
  }else if(a[i]<b[j]){
    ++i;
  }else{
    ++j;
  }
}

如果不需要使用向量,则可以使用 std::multiset 作为两个集合中值的容器。

这个 std::multiset 容器允许插入重复值并同时对值进行排序。您可以使用 std::multiset::count 获取元素的数量。

将以 O(logN( 复杂度执行一次检查,以检查 B 中的所有值是否都包含在 A 中,并且在最坏情况下重复复杂度的计数为 M(logN(。使用std::map也可以实现相同的效果,但集合比map占用更少的内存,并且使用起来更简单。

如果一个值在集合 B 中多次出现,则只能在集合 A 中进行一次检查。