如何优化检查其中一个给定的数组是否包含在另一个数组中

时间:2014-06-05 11:12:47

标签: java android algorithm optimization

我有一个整数数组,每个时间间隔更新一个新值(让我们称之为数据)。当发生这种情况时,我想检查该数组是否包含来自指定集合的​​任何其他整数数组(让我们调用该集合)。 我是这样做的:

  • 将子数组与长度为X的数据末尾分开(集合中的数组的最大长度设置为X);
  • 通过集合进行迭代,并检查其中是否包含任何数组;

虽然看起来不是最佳的,但确实有效。但我所有的其他想法都涉及创建更多集合(例如,创建一个原始集合中所有数组的集合,以与数据相同的整数结束,重复)。这似乎更复杂(另一方面,它看起来是处理集合中没有有限最大长度的数组的唯一方法)。

是否有任何标准算法来处理这样的问题?如果没有,我可以对我的方法进行任何有价值的优化吗?

编辑: 确切地说,我:

  • 将一个子数组与长度为X的数据末尾分开(集合中的数组的最大长度设置为X,如果不是它只是集合中最长的数据的长度);
  • 通过集合和其中的每个数组进行迭代:
    • 与前一个子数组分开的子数组,其长度与集合中的当前数组匹配;
    • 使用Java的List.equals来比较数组;

编辑2: 感谢所有的回放,他们肯定有一天会派上用场。在这种情况下,我决定放弃最后的步骤,只是比较我自己的循环中的数组。这消除了创建另一个子阵列并且它已经是O(N),所以在这种特定情况下会这样做。

4 个答案:

答案 0 :(得分:1)

看看KMP algorithm。它的设计考虑了字符串匹配,但它实际上归结为将数组的子序列与给定序列匹配。由于该算法具有线性复杂度(O(n)),因此可以说它非常优化。它也是标准算法的基本主要内容。

如果您将当前产品与主阵列一起保存,并且可以在O(1)中进行检查,那么dfens建议是明智的,因为它不会产生明显的额外复杂性,但它也非常脆弱并且产生许多误报和否定。想象一下目标数组[1,1,...,1],它将始终为所有非平凡主阵列产生正测试。当一个桶包含0时,它也会崩溃。这意味着对他的测试的成功检查始终是命中的必要条件(0s除外),但是永远不够 - 仅使用该方法,您永远无法确定这个结果的有效性。

答案 1 :(得分:1)

查看rsync算法...如果我理解正确,你可以去做:

您拥有大量数据[长度L]

在该数据的末尾,您已经获得了N个字节的数据,并且您想知道之前是否出现过这些N个字节。

预先计算:

对于数组中的每个偏移量,计算下N个数据元素的校验和。 将该校验和保存在单独的数组中。

使用像rsync这样的滚动校验和,你可以在所有元素的O(N)时间内执行此步骤..

每当有新数据到达时:

计算最后N个元素的校验和。使用滚动校验和,这可能是O(1)

检查所有预先计算的校验和的校验和。如果匹配,检查子数组的相等性(子数,无论......)。如果匹配也匹配。

我认为,实质上这与dfen的所有数字产品的方法相同。

答案 2 :(得分:0)

我认为您可以保留阵列产品以立即拒绝。

因此,如果您的数组是[n_1,n_2,n_3,...],那么如果产品[m_1,m_2,m_3,...] = M不能被产品m_1*m_2*... = N整除,则可以说它不是n_1*n_2*...的子数组。 / p>

实施例

假设你有阵列

[6,7]

与之相比:

[6,10,12]

[4,6,7]

您的数组产品为6*7 = 42

6 * 10 * 12 = 720不能被42整除,因此你可以立即拒绝第一个数组

[4, 6, 7]可以被42分割(但你不能拒绝它 - 它可以有其他乘数)

在每个时间间隔内,您可以将产品乘以新数字,以避免每次都计算整个产品。

答案 3 :(得分:0)

请注意,如果您自己模拟List的{​​{1}},则无需分配任何内容。再多一个循环。

与dfens的答案类似,我会提供其他标准:

  • 由于产品太大而无法有效处理,请改为计算GCD。它会产生更多误报,但肯定适合equalslong或任何原始数据类型。
  • 计算尾随零的总数,即“产品”忽略所有因素但功率为2.也非常弱,但速度很快。在更耗时的标准之前使用此标准。

但是......这是DThought答案的一个特例。使用滚动哈希。