处理大型数组时超出时间限制

Posted

技术标签:

【中文标题】处理大型数组时超出时间限制【英文标题】:Time Limit Exceeded in dealing with large arrays 【发布时间】:2014-11-11 05:39:08 【问题描述】:

我正在尝试解决this question:

我们都知道 Varchas 正在进行中。所以 FOC 想组织一个名为“发现事件”的活动。

任务很简单:

给定一个正整数数组 A[1...N]。会有Q查询。在查询中,您将获得一个整数。您需要找出给定数组中该整数的频率。

输入:

输入的第一行包含整数 N,即给定数组中的整数个数。 下一行将包含 N 个空格分隔的整数。下一行是 Q,查询数。 接下来的 Q 行将包含一个整数,您应该找出它的出现次数。

输出:

为每个查询输出单个整数,即给定整数的频率。

约束:

1

1

0

这是我的代码:

#include <iostream>
using namespace std;

int main()

    long long n=0;
    cin >> n;
    long long a[1000000];
    for (int i=1;i<=n;i++)
    
        cin >> a[i];
    
    long long q=0;
    cin >> q;
    while (q--)
    
        long long temp=0,counter=0;
        cin >> temp;
        for (int k=1;k<=n;k++)
        
            if (a[k]==temp)
                counter++;
        
        cout << "\n" << counter;
        temp=0;
        counter=0;
    
    return 0;

但是,我遇到了“超出时间限制”错误。我怀疑这是由于无法处理数组中的大值。谁能告诉我如何处理这么大的数组?

【问题讨论】:

请让您的问题自给自足,而不是提供链接。 问题要求您首先对数组进行排序,然后对于每个查询,您只需进行二进制搜索并找到包含该值的范围并打印范围的长度 问题是每次查询,都需要扫描整个数组,时间复杂度为O(n^2),显然是TLE @Smac89:问题不在于范围查询,它比这简单得多。问题是要求计算整数的频率。 啊,我知道你们现在在做什么。我通常会追求内存效率,因为你们依赖于 Q 很小的事实。这很好,但它不适用于大 Q 【参考方案1】:

失败在于算法本身,请注意,对于每个查询,您都会遍历整个数组。有 100,000 个查询和 100,000 个元素。这意味着在更坏的情况下,您将遍历 100,000 * 100,000 个元素 = 10,000,000,000 个元素,这不会及时完成。如果你使用Big-O notation分析复杂度,你的算法是O(nq),对于这个问题来说太慢了,因为n*q很大。

你应该做的是在进行任何查询之前计算分数,然后存储在一个数组中(这就是给出A[i]的范围的原因。你应该能够通过遍历数组来做到这一点只有一次。(提示:您不需要将输入存储到数组中,直接计数即可)。

通过这样做,算法将只是O(n),并且由于n 足够小(根据经验,小于一百万是小的),它应该及时完成。

然后您可以立即回答每个查询,从而使您的程序足够快以达到时间限制。

您可以改进的另一件事是数组的数据类型。存储在该数组中的值不会大于 100 万,因此您不需要使用更多内存的 long long。你可以使用int

【讨论】:

我可以用向量代替数组吗? @user2295715:当然,您需要随机访问。这是由std::dequestd::vector 提供的,而不是由std::list 提供的。【参考方案2】:

您的算法效率低下。您将所有数字读入一个数组,然后在数组中线性搜索每个查询。

你应该做的是做一组计数。换句话说,如果您阅读数字 5,请执行 count[5]++。然后对于每个查询,您所要做的就是从数组中返回计数。例如,数组中有多少个 5?答案:count[5]。

【讨论】:

【参考方案3】:

由于您的最大数量可以是 10^6,我认为您的问题将超出内存限制,即使它及时合适。另一种解决方案是对数组进行排序(您可以使用 STL 排序函数在 N*logN 中进行排序),并且对于每个查询,您可以进行两次二进制搜索。第一个用于查找元素出现的第一个位置,第二个用于查找元素出现的最后一个位置,因此每个查询的答案将是 lastPosition - firstPosition + 1。

【讨论】:

以上是关于处理大型数组时超出时间限制的主要内容,如果未能解决你的问题,请参考以下文章

为啥更改数组的顺序会导致超出时间限制?

避免“超出 GC 开销限制”错误

将大型数据集缓存到 spark 内存中时“超出 GC 开销限制”(通过 sparklyr 和 RStudio)

更改python中的分配顺序时“超出时间限制”

多部分正文长度限制超出异常

http不返回数据,是超出了nginx返回的长度限制?还是有其他原因?