如何在L,R范围内的数组中找到最频繁的数字及其频率?

时间:2016-10-28 09:46:37

标签: arrays algorithm data-structures logic

假设我们得到一个长度为A[]的数组N,我们必须回答Q个查询,其中包含两个整数L,R。我们必须找到A[L]A[R]的数字,其频率至少为(R-L+1)/2。如果不存在这样的号码,那么我们必须打印“没有这样的号码”

我只能考虑O(Q*(R-L))运行频率计数器的方法,并首先从L to R获取数组中最常用的数字。然后计算它的频率。

但需要进行更多优化。

约束: 1<= N <= 3*10^5 ,, 1<=Q<=10^51<=L<=R<=N

1 个答案:

答案 0 :(得分:2)

我知道O((N + Q) * sqrt(N))解决方案:

  1. 如果在阵列中发生至少B次,请拨打一个号码。数组中最多有N / B个重数。

  2. 如果查询段是&#34;短&#34; (R - L + 1 < 2 * B),我们可以在O(B)时间内回答它(通过简单地遍历范围的所有元素)。

  3. 如果查询段是&#34; long&#34; (R - L + 1 >= 2 * B),频繁的元素必须很重。我们可以迭代所有重数,然后检查是否至少有一个匹配(为此,我们可以预先计算每个重元素的出现次数的前缀和,并在[L, R]段中找到它出现的次数时间)。

  4. 如果我们为某个常量B = C * sqrt(N)设置C,则此解决方案将在O((N + Q) * sqrt(N))时间运行并使用O(N * sqrt(N))内存。正确选择C,可能符合时间和内存限制。

    还有一个在O(N + Q * log N * k)时间内运行的随机解决方案。

    1. 让我们为数组中的每个唯一元素存储一个出现位置的向量。现在我们可以在O(log N)时间内找到固定范围内固定元素的出现次数(对出现的向量进行两次二进制搜索)。

    2. 对于每个查询,我们都会执行以下操作:

      • 从细分中选择一个随机元素
      • 如上所述在O(log N)时间内检查其出现次数
      • 如果它足够频繁,我们就完成了。否则,我们选择另一个随机元素并执行相同的
      • 如果存在频繁元素,则每次试验的不选择概率不超过1 / 2。如果我们执行k次,则找不到它的概率为(1 / 2) ^ k
    3. 正确选择k(以便每个查询的O(k * log N)足够快且(1 / 2) ^ k相当小),此解决方案应该通过。

      两种解决方案都易于编码(第一种只需要前缀和,第二种只使用出现的向量和二进制搜索)。如果我必须对它们进行编码,我会选择后者(前者可能会更加痛苦地挤压时间和内存限制)。