满足约束的久负盛名子阵列的数量

时间:2015-08-13 14:33:15

标签: algorithm number-theory

给定数组A,找到满足条件的连续子​​数组的数量:

  

子阵列中没有对(i,j)i < jA[i] mod A[j]= M

1<=A[i]<=100000

  

我的方法:在O(n^2)时间复杂度中采用天真的方式,这很糟糕。

我可以将其缩小为(nlogn)吗?

2 个答案:

答案 0 :(得分:0)

基本上,我们需要找到所有对i < jA[i] mod A[j] = M

如果a mod b = m,则a mod d = m, where d is a divisor of b and d > m

散列数组中的数字。对于数组中的每个数字a,检查a - ma - m的任何除数是否为数组中的元素且其索引是否大于a的索引 - 枚举(a, a - m)中的任何现有对(a, divisor of (a - m) > m)O(n sqrt n)

显然,任何满足条件的连续子​​阵列都位于任何这样的对之间。如果我们在区间树中聚合对,当我们遍历数组时,我们可以在O(log n)时间内测试我们是否在一对中。一旦我们检测到我们正在重叠一对(树中的间隔),我们将窗口重置为(i + 1, j)(其中(i,j)是间隔)并继续计数;我们根据公式segment * (segment + 1) / 2将可实现的最大段添加到总数中,减去先前的重叠计数。

答案 1 :(得分:0)

这是O(N)时间复杂度,但需要O(N + M)空间复杂度:

  • 我们扫描数组并执行A [i] = A [i] mod M
  • 保持一个大小为N的计数器数组,它在跟踪给定条件之前跟踪多少元素(基本上不等于当前元素):
  • C [i] =元素A [j]的数量,使得A [j]!= A [i]其中j

考虑数组:

  • 原作阵列:12,25,16,14,37,18,28,17,9,37
  • 新A数组:0,1,4,2,1,6,4,5,9,1(A [i] mod M)
  • 计数器阵列:0,1,2,3,2,3,3,4,5,4

计数器数组可以根据以前的值逐步构造:

  • A [j] = A [i]和j
  • 否则C [i] = C [i-1] +1;

当在索引i之前查找A [i]的最后一次出现时,我们需要保留字典(A [i],last-index-of-A [i])以进行快速查找。 因为我们只保留A [i] mod M =&gt;的值。一个O(M)字典会做。

我们现在只是总结计数器数组值:

Number of contiguous subarrays = Sum(C)

在这种情况下,我们将有27个连续的子阵列,这些子阵列都符合这一条件。