xor在数组

时间:2017-09-10 19:00:03

标签: arrays algorithm filter series xor

我们有一个原始数组和一个过滤器列表,其中每个过滤器都包含允许通过过滤器的索引。过滤器相当不错,例如它们按以下方式对每个2的幂进行分组(过滤器最多为n = 20)。

  • 1 (2^0) = 1 3 5 7 9 11 13 15 17 19
  • 2 (2^1) = 1 2 5 6 9 10 13 14 17 18
  • 4 (2^2) = 1 2 3 4 9 10 11 12 17 18 19 20
  • 8 (2^3) = 1 2 3 4 5 6 7 8 17 18 19 20

我希望你明白这个主意。现在我们将部分或全部这些过滤器(用户指示要应用哪些过滤器)应用于原始数组,并且转换数组的元素的xor就是答案。举一个例子,如果原始数组是[3 7 8 1 2 9 6 4 11],例如n = 9,我们需要应用4,2和1的过滤器,转换将是这样的。

  • 应用4 - [3 7 8 1 x x x x 11]
  • 过滤器后
  • 应用2 - [3 7 x x x x x x 11]
  • 过滤器后
  • 应用1 - [3 x x x x x x x 11]
  • 过滤器后

现在是3和11的xor,例如8是答案。我可以解决这个O(n * no。过滤器)时间,但我需要一个更好的解决方案,它可能在O(没有过滤器)时间给出答案。有没有办法利用xor的属性和/或预先计算一些结果,然后给出过滤器的答案。这是因为有很多带过滤器的查询,所以我需要在O(没有过滤器)时间内回答查询。任何形式的帮助将不胜感激。

1 个答案:

答案 0 :(得分:0)

可以在O(M)中完成,其中M是通过以特定方式迭代数组通过所有过滤器的项目数(与过滤器数无关),仅生成通过所有过滤器的索引

如果您从零开始写下示例,则更容易看到:

  • 1:0 2 4 6 8 10 12 14 16 18(不包含1的数字)
  • 2:0 1 4 5 8 9 12 13 16 17(不包含2的数字等)
  • 4:0 1 2 3 8 9 10 11 16 17 18 19
  • 8:0 1 2 3 4 5 6 7 16 17 18 19

过滤器实际上只是对数组中索引位的约束。该约束的格式为index & filters = 0,其中filters只是所有单个过滤器的总和(例如1 + 2 + 4 = 7)。给定有效索引i,可以仅使用基本操作来计算下一个有效索引i'i' = (i | filters) + 1 & ~filters。这里的想法是将被过滤的位设置为零,这样+1将通过它们,然后再次清除过滤的位以使索引有效。总效果是未经滤波的位递增,滤波后的位保持为零。

这提供了一种简单的算法,可以直接遍历所有有效索引。从0开始(始终有效)并使用上面的规则递增,直到到达数组的末尾:

for (int i = 0; i < N; i = (i | filters) + 1 & ~filters)
    // do something with array[i], like XOR them all together