当前位置: 首页 > 知识库问答 >
问题:

如何得到O(mn)中两个稀疏向量的点积,其中m和n是两个向量中的元素数

孔城
2023-03-14

我有两个稀疏向量X和Y,想要得到O(mn)中的点积,其中m和n是X和Y中非零元素的数量。我能想到的唯一方法是选取向量X中的每个元素,遍历向量Y,以找到是否有具有相同索引的元素。但这需要O(m*n)。我将向量实现为一个链表,每个节点都有一个元素。

共有3个答案

路阳华
2023-03-14
 Use Map to store each vector.
 Each entry of map has index as key and value as the vector value at the particular index. Insert only the non zero values 
 Iterate on one map and for each entry check whether the particular key is present in the other map.If yes update the product else ignore the current key
 Time Complexity :  n -> vector size
                   O(n) - for map construction 
                   O(n) - for iteration 
 Space Complexity :  O(n) - for maps
须捷
2023-03-14

假设非零元素是通过两个向量中的坐标索引排序的,那么它是通过合并算法实现的。这是计算机科学中的一个标准算法,它将两个排序序列合并成一个排序序列,并且在O(mn)中工作。

有两种方法可以做到这一点。第一个是检查合并中是否有相等的元素。而且确实是最好的办法。

第二种方法是先合并,然后检查相等(它们必须是连续的):

std::pair<int, double> vecA[n], vecB[m], vecBoth[n+m];
std::merge(vecA, vecA+n, vecB, vecB+m, vecBoth);
double dotP = 0.0;
for (int i = 0; i+1 < n+m; i++)
  if (vecBoth[i].first == vecBoth[i+1].first)
    dotP += vecBoth[i].second * vecBoth[i+1].second;

std::合并复杂度为O(M N)。

上面的示例假设数据存储在数组中(这是稀疏向量和矩阵的最佳选择)。如果您想使用链表,还可以在O(M N)时间内执行合并,请参见此问题。

即使列表未排序,也可以在O(MN)时间内执行点积。其思想是首先将A的所有元素放入哈希表,然后遍历B的元素,查看哈希表中是否有具有相同索引的元素。

如果索引非常大(例如超过百万),那么您可能真的应该使用一个非平凡的哈希函数。然而,若索引很小,那个么可以避免使用哈希函数。只需使用大于向量维数的数组。为了快速清除此阵列,您可以使用“世代”技巧。

//global data! must be threadlocal in case of concurrent access
double elemsTable[1<<20];
int whenUsed[1<<20] = {0};
int usedGeneration = 0;

double CalcDotProduct(std::pair<int, double> vecA[n], vecB[m]) {
  usedGeneration++;   //clear used array in O(1)
  for (int i = 0; i < n; i++) {
    elemsTable[vecA[i].first] = vecA[i].second;
    whenUsed[vecA[i].first] = usedGeneration;
  }
  double dotP = 0.0;
  for (int i = 0; i < m; i++)
    if (whenUsed[vecB[i].first] == usedGeneration)
      dotP += elemsTable[vecB[i].first] * vecB[i].second;
  return dotP;
}

请注意,您可能需要清除每十亿个点积一次的whenuse

仉昱
2023-03-14

如果向量存储为元组的链接列表,每个元组包含索引和非零元素的值,并按索引排序,则可以执行此操作。

通过从位于较低索引处的向量中选择下一个元素,可以遍历这两个向量。如果索引相同,则将元素相乘并存储结果。

重复此操作,直到一个列表到达末尾。

由于在每个列表中每个非零元素都有一个步骤,因此所需的复杂度为O(m n)。

脚注:数据结构不必是链表,但必须提供一种O(1)方式来访问下一个非0元素及其索引。

 类似资料:
  • 问题内容: 我在看Hough Transform的Opencv Java文档 。 返回值的数据类型描述为: 线的输出向量。每行由一个二元素矢量(rho,θ)表示。rho是距坐标原点(0,0)(图像的左上角)的距离。theta是弧度的直线旋转角度(0〜垂直线,pi / 2〜水平线)。 奇怪的是,此描述与C ++接口的描述匹配, 但是 数据类型与之不匹配:在C 中,您可以 按照本教程中的描述使用a 。

  • 我还有一张这样的单子: 如您所见,中的某些向量与中的向量部分匹配。在某些情况下,中的向量与中的部分向量完全匹配。例如,中的的最后一个值与的第五个组件中的向量匹配,但与之不匹配,尽管存在公共值。在中的中的值(“未达到”、“不是选项”、“省略”)按此顺序一起在中的任何向量中都不匹配。对于中的的值也是相同的。 我试图实现的是将中的每个向量中的元素与中的每个向量进行比较,提取通用的值并以相同的顺序匹配中的

  • 问题内容: 最近,Elasticsearch允许在查询中使用向量和稀疏向量。在他们的文档之后,我发现了一个错误,本质上是: 似乎“嵌入”不是一个成功的领域。 我将文档上传到Elasticsearch如下: 我为每个文档创建一个json文件 我在Python中加载json文件 我将这些objetcs传递给Elasticsearch: 这是我的json文件的结构(请注意,嵌入是字典,因为它是稀疏向量)

  • 但它给出了一个错误。 我对Spark是新手,所以这可能很明显,在我的代码行中可能有明显的错误。请帮忙。谢谢!

  • 这应该很容易,但我一直在撞我的头。 我有数字向量 我有一个数值向量v2。v2始终是v1的子集。 我想从v1中删除v2中的所有元素,但每个v2元素只删除一个(而且完全是一个)v1元素。 所需输出 如果我希望将保留在v1之外。使用很容易。 如果我希望将与v1保持一致。此外,也能起到作用。 如果我希望将与v1保持一致。现在返回。不是我想要的。 当答案输入时,我很可能会用头撞我的键盘,但现在我还没有得到最

  • 问题内容: 在此代码片段中,我无法总结和: 由于和定义为,此代码将连接字符串和输出。 我怎样才能得到它,而不是总结和输出? 问题答案: Java提供了原始类型的解析方法。因此,根据您的输入,您可以使用Integer.parseInt,Double.parseDouble或其他。