【问题标题】:Maxima counting最大值计数
【发布时间】:2015-11-01 23:28:39
【问题描述】:

A = {4, 1, 3, 2}

有 10 个连续的子数组。让我考虑所有这些子数组的最大值。

  Sub array   Max 

{4}            4
{1}            1
{3}            3
{2}            2
{4, 1}         4
{1, 3}         3
{3, 2}         3
{4, 1, 3}      4
{1, 3, 2}      3
{4, 1, 3, 2}   4

所以:

Max #    Occurrences
 1           1
 2           1
 3           4
 4           4

问题: 有没有什么方法可以统计O(n) 时间内出现的次数?使用 dequeue 我可以找到所有间隔的最大值,但这需要O(n^2 log n) 时间,这对于大型数组是不可行的。

【问题讨论】:

  • 你可以试试Fenwick tree。不过可以在N log N
  • @James 你能详细说明如何使用它吗?
  • 你是只对max=4的子数组感兴趣,还是对所有最大值的频率感兴趣?
  • 我在这里实现了对这个问题的 O(n log n) 答案:stackoverflow.com/a/31945031/1327235

标签: algorithm max


【解决方案1】:

该算法将首先找到全局最大值,它们在它们所在的所有间隔上都是最大值(计算它们应该是O(N),尽管多个全局最大值会使复杂性有点复杂)。然后您知道对于超出或包含全局最大值的区间,其他最大值不会是最大值,因此您可以将问题分解为子数组。

例如,对于您的数组,您首先会观察到4 是数组的最大值,因此它是从0 或之前开始并在0 或之后结束的所有子数组的最大值,即4。然后你得到前面和后面的子数组{}{1, 3, 2}。然后你继续检查{1, 3, 2}(我们跳过空的,因为它很简单)3 是最大值,它是它所在的所有子数组的最大值,即那些从1 或之前开始并结束的子数组在1 或之后,有四个这样的(2*2),然后继续使用子数组{1}{2}

还必须考虑我们遇到多个最大值的并发症。例如,如果我们在数组{1, 4, 3, 4, 3, 2} 中,你会发现两个最大值(两个四),这同样适用于第一个4 是它所属的所有区间的最大值(这里是10)和在12 中,第二个是最大值,但要注意其中一些间隔是相同的,您必须决定如何计算它们(见下文)。现在这同样适用于其他数字只能在 4 不在的子数组中为最大值,因此我们最终需要考虑 3 个子数组,即 {1}{3}{3, 2}

当你在一个区间中有多个最大值时,你想如何计算它们就不会那么明确了。例如在区间{4, 3, 4}中,4在区间{4}(第一个)、{4}(第二个)、{4, 3}{3, 4}{4, 3, 4}中最大。除了最新的,其他的都很直接,有一个,但你想怎么计算最后一个?好吧,这是一个间隔,所以它是一个,但你也可以决定计算两次。根据算法分析数组时,您最终会得到第一个在3 间隔中最大,第二个在3 间隔中加起来为6,这对应于您计算最后一个间隔两次(因为它有两个4s)。

另一方面,如果您只想计算间隔一次,例如可以使用子数组来计算间隔。您首先构建包含它们中的每一个的最大子区间和包含两者的最大子区间。例如,在数组{1, 4, 3, 4, 3, 2} 中,首先有子数组在第一个4 之前或之后开始,在第一个4 或之后结束,但在第二个之前(这意味着你得到4 间隔),然后你对第二个执行相应的操作,这意味着间隔从第二个 4 开始或之前,但在第一个之后并在第二个 4 或之后结束(这意味着你得到6 间隔),最后你计算它们包含两者这是从第一个4 或之前开始到第二个6 或之后结束的间隔(这给出了6 间隔)。当我们总结时,我们最终得到16 间隔。

另一种解决方案是选择4s 中的一个作为最大值,然后处理相应子数组中剩余的4s。在这个例子中,可能会选择第二个,因为它是最中间的4。这将导致计算12 间隔,然后当您处理左子间隔({1, 4, 3})时,您会发现44 间隔中的最大值。它还将增加 16 间隔,其中 4 是最大值。

算法平均在O(N log N) 时间和O(N^2) 时间在最坏的情况下执行此操作,如果您使用天真的方法来查找子数组中的最大值(即O(N))。但是,使用segment trees,您应该能够在(一次)构建段树(即O(N))之后将子数组中的最大值减少为O(log N) 操作。在构建分段树之后,最坏的情况将是O(N log N) 和平均O((log N)^2)。在最坏的情况下,计数决定了复杂性,所以它是O(N log N),平均而言,段树的构建占主导地位,所以它是O(N)

【讨论】:

  • 您能否使用示例 A = {4, 1, 3, 2, 5, 4, 1} 详细说明您的算法
  • 非常感谢。现在我将尝试实现它。
  • 更正前4个有10个子区间,第二个有12个。但要注意这里的10 + 12 = 21。
  • @Stef 我认为它甚至比21 还要少,我认为这个例子是15。您需要删除所有包含4 的子数组的1{4, 3, 4}{1, 4, 3, 4}{1, 4, 3, 4, 3}{1, 4, 3, 4, 3, 2}{4, 3, 4, 3}{4, 3, 4, 3, 2}
  • @Holt:有一个数据结构:我听说它称为segment tree(尽管令人困惑的是,它与what Wikipedia calls by that name 并不完全相同)。您需要为整个数组构建一次,这需要 O(n) 时间和空间,但在给定间隔内的最大值的每个查询在最坏的情况下需要 O(n log n) 时间。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-10-29
  • 2012-01-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多