【问题标题】:How to quickly find the maximum-average interval?如何快速找到最大平均间隔?
【发布时间】:2012-08-26 06:56:02
【问题描述】:

从整数数组A[N],我想找到一个区间[i,j],它的平均值为(A[i] + A[i + 1] + .. + A[j]) / (j - i + 1)

区间(j - i + 1)的长度应该大于L.(L >= 1)

我以为是对每一个i~j计算一个平均值,但是这样做太慢了。(N太大了)

有比O(N^2) 更快的算法吗?或者我想知道是否存在一种随机方法。

【问题讨论】:

  • 你能发一个简短的例子吗?
  • 你需要 L >= 2,对于 L >= 1,你可以只返回 [i,i] 其中 i 是最大索引
  • @barak1412:我相信他的意思是L是动态给算法的参数。
  • 我不是这么理解的。他最好举个例子
  • Goldwasser 等人报告了一种 O(N) 算法。在arxiv.org/abs/cs/0207026。您可以下载该论文的 pdf。你也可以在这里找到一个 O(N*logL) 的:csie.ntu.edu.tw/~kmchao/seq04spr/jcss.pdf

标签: algorithm


【解决方案1】:

有一个O(N*logC) 算法,其中C 与数组的最大元素值成正比。与近期论文中一些比较复杂的算法相比,该算法更容易理解,并且可以在短时间内实现,并且在实际应用中仍然足够快。

为简单起见,我们假设数组中至少有一个非负整数。

该算法基于二分查找。起初,我们可以发现最终的答案必须在[0, max(A)]的范围内,我们在每次迭代中将这个区间减半,直到它足够小(例如10-6)。在每次迭代中,假设可用区间为[a,b],我们需要检查最大平均值是否不小于(a+b)/2。如果是这样,我们得到一个更小的区间[(a+b)/2, b],否则我们得到[a, (a+b)/2]

现在的问题是:给定一个数字K,如何检查最终答案至少是K

假设平均值至少为K,则存在一些ij,这样(A[i] + A[i+1] + ... + A[j]) / (j - i + 1) >= K。我们将两边都乘以(j-i+1),然后将右侧向左移动,得到(A[i] - K) + (A[i+1] - K) + ... + (A[j] - K) >= 0

所以,让B[i] = A[i] - K,我们只需要找到一个区间[i, j] (j - i + 1 > L) 使得B[i] + ... + B[j] >= 0。现在问题是:给定数组B和长度L,我们要找到一个长度大于L的最大和的区间。如果最大和为>= 0,则原来的平均数K是可能的。

第二个问题可以通过线性扫描来解决。让sumB[0] = 0sumB[i] = B[1] + B[2] + ... + B[i]。对于每个索引i,以B[i] 结束的最大和间隔为sumB[i] - min(sumB[0], sumB[1], ..., sumB[i-L-1])。当扫描i增加的数组时,我们可以动态维护min(sumB[0], ..., sumB[i-L-1])

子问题的时间复杂度为O(N)。而且我们需要O(logC) 迭代,所以总复杂度是O(N*logC)

附:这种“平均问题”属于称为fractional programming 的问题家族。类似的问题还有最小平均加权生成树、最小平均加权循环等。

附:再次。 O(logC) 是一个松散的界限。我认为我们可以通过仔细分析来减少它。

【讨论】:

  • +1 这在第一次阅读时并没有被理解,但你实际上已经很好地解释了它。此外,阅读此链接的答案对我有帮助:activities.tjhsst.edu/sct/lectures/1112/binary102111.pdf
  • 为什么是 sumB[0] = 0 ?我尝试实施该解决方案,我认为 sumB[0] 应该分配给 B[0]。你能澄清一下吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多