超出内存限制或时间限制

Posted

技术标签:

【中文标题】超出内存限制或时间限制【英文标题】:Exceeding memory limit or time limit 【发布时间】:2015-12-10 05:40:38 【问题描述】:

我正在尝试创建一个程序,它将向量 1 ('V1') 中的 3 个不相等的位置相乘,并找到最大乘法。

我正在使用 3 个“for”循环来进行计数和写作。程序获取位置量“N”,然后是“input.txt”中的所有“N”个数字。之后,它获取最大位置'max'并写入'output.exe'。

但我需要使程序尽可能高效,16 MB 内存限制和 1 秒时间限制(我得到 1.004 秒和 33 MB)。有没有更有效的方法来做到这一点?

#include <vector>
#include <fstream>
#include <iostream>
#include <algorithm>

using namespace std;

int main()

    int N;
    long long max = -9223372036854775807;
    int input;

    vector<long long> V1;

    ifstream file1;
    file1.open("input.txt");
    file1 >> N;

    V1.resize(N);

    for (int i = 0; i < N; i++)
    
        file1 >> V1[i];
    

    for (int i = 0; i < N; i++)
        for (int j = 0; j < i; j++)
            for (int k = 0; k < j; k++)
                if (V1[i] * V1[j] * V1[k] > max)
                
                    max = V1[i] * V1[j] * V1[k];
                

    ofstream file2;
    file2.open("output.txt");
    file2 << max;
    file2.close();

文件 Input.txt

 5
    10 10 10 -300 - 300

【问题讨论】:

避免计算和pop_back 先做if 可以给一点。嗯...你需要if吗? 也许V1.resizepush_back 之前会有帮助。如果你这样做,你只会分配一个内存。 感谢您的帮助,If 是该程序上一个版本的剩余部分,我现在将其删除。现在我使用 1 个整数而不是整个向量来存储最大数量。 那么你应该更新你的描述。描述类型表明程序必须将结果存储在向量中。但是现在您已经将要求更改为:找到最大值。那是两个非常不同的程序。 :-) 【参考方案1】:

通过查看您所做的工作,您必须找到给定输入向量中 3 个数字的乘积中的最大值。

只需对向量 V1 进行排序并输出(第一个 3 个元素或第一个和最后两个元素的乘积)的最大值。这在空间和时间上都很有效。

像这样:

sort(V1.begin(),V1.end(),greater<int>())   //sorts in descending order
int n = V1.size()-1;
output max(V1[0] * V1[1] * V1[2], V1[0] * V1[n] * V1[n-1])

【讨论】:

想象以下输入:1 2 3 -10000 -10000。你的程序输出6,而正确答案是300,000,000 哦...我错过了那个案例...我会为此编辑我的答案。谢谢你的案子……另外,我认为没有其他案子会违反这一点。 不错的一个:) 我也无法想象一个破案。只是为了澄清 - 此算法需要 O(N * log(N)) 时间。 是的,需要 n * log(n) 时间。【参考方案2】:

我想到的第一个 - 为什么要存储这些值?您只需要单个最大值 - 无需存储所有这些值,推送它们,此外,将它们整理出来。

另一个重要通知:

你有一个long long的向量,但你读到了ints。由于您输入的数字很大,因此请在任何地方使用long long 推送一个项目并将其弹回是没有意义的 - 您应该在推送之前检查它以避免两次不必要的操作 无论如何,您根本不需要比较 ijk 是否相等 - 根据您的循环限制,它们永远不会相等 当您知道项目编号错误时,将项目推送到数组中。扩展向量需要更多时间。您可能希望将其调整为给定大小。

大概,这段代码会满足你的记忆\时间要求:

int N; 
long long maximum = -9223372036854775807; // Subject to limits.h LLONG_MIN usage
vector<long long> V1;

ifstream file1;
file1.open("input.txt");
file1 >> N;

V1.resize(N);

for (int i = 0; i < N; i++)
    file1 >> V1[i];


file1.close();

for (int i = 0; i < N; i++)
    for (int j = 0; j < i; j++)
        for (int k = 0; k < j; k++)
            if (V1[i] * V1[j] * V1[k] > maximum)
                maximum = V1[i] * V1[j] * V1[k];                

ofstream file2;
file2.open("output.txt");
file2 << maximum;
file2.close();

【讨论】:

感谢您的帮助!但现在我有另一个问题,当我输入 3 30000 30000 3000 时程序显示错误答案 @AramayisAntonyan 好吧,我的错。我到处都使用int 而不是long long。请检查更新的答案。 @YeldarKurmangaliyev:您需要将V1.reserve(N); 更改为V1.resize(N);。当您只保留时,向量仍然是“空的”并且访问这些元素是未定义的行为。 @Blastfurnace 感谢您的澄清 :) 我已经更新了答案。 我更新了程序,但它仍然超时,当我输入 3 30000 30000 3000 时给出 1.36【参考方案3】:

嗯,一旦我看到大小和时间减少,我倾向于删除所有不必要的语言好东西,因为它们确实有助于正确编程,但只会消耗资源。

因此,如果您真的想保留值列表的不同索引的所有产品,我建议您丢弃向量,推送和弹出并使用固定大小的数组。

但在进行低级优化之前,我们必须考虑所有可能的算法优化。您只希望从列表中提取的三个不同值中尽可能地成为最大的产品。但是对于正数,a >= b a *c >= b *c 并且两个负数的乘积是正数。

所以最高的产品可能只来自:

三个最高正值的乘积 一个最高正值和两个最低负值的乘积(绝对值最高) 三个最高负值的乘积(如果没有正值)

所以你甚至不需要加载完整的初始向量,只需保留:

三个最高正值 三个最高负值 两个最低的负值

您可以通过在读取时间以 O(n) 时间存储它们来获取它们,并且只存储八个值。如果你只有五个值,它根本就没有效率,但是无论你处理多少个值,它都会在时间上是线性的并且大小是恒定的。

可能的实现:

#include <iostream>
#include <fstream>
#include <climits>

using namespace std;

class Max3 
    long long pmax[3];
    long long nmax[3];
    long long nmin[2];

    void push(long long *record, long long val, size_t pos) 
        for(size_t i=0; i<pos; i++) 
            record[i] = record[i + 1];
        
        record[pos] = val;
    

    void set(long long *record, long long val, size_t sz) 
        for (size_t i=1; i<sz; i++) 
            if (val < record[i]) 
                push(record, val, i - 1);
                return;
            
        
        push(record, val, sz - 1);
    

public:
    Max3() 
        size_t i;
        for (i=0; i<sizeof(pmax)/sizeof(pmax[0]); i++)
            pmax[i] = 0;
        for (i=0; i<sizeof(nmin)/sizeof(nmin[0]); i++)
            nmin[i] = 0;
        for (i=0; i<sizeof(nmax)/sizeof(nmax[0]); i++)
            nmax[i] = LLONG_MIN;
    

    void test(long long val) 
        if (val >= *pmax) 
            set(pmax, val, 3);
        
        else if (val <= 0) 
            if (val <= *nmin) 
                set(nmin, -val, 2);
            
            if (val >= *nmax) 
                set(nmax, val, 3);
            
        
    

    long long getMax() 
        long long max = 0, prod, pm;
        if ((prod = pmax[0] * pmax[1] * pmax[2]) > max)
            max = prod;

        if (pmax[2] > 0)
            pm = pmax[2];
        else if (pmax[1] > 0)
            pm = pmax[1];
        else
            pm = pmax[0];

        if ((prod = nmin[0] * nmin[1] * pm) > max)
            max = prod;

        if ((prod = nmax[0] * nmax[1] * nmax[2]) > max)
            max = prod;
        return max;
    
;


int main() 
    int N;
    long long input;
    Max3 m3;

    ifstream file1;
    file1.open("input.txt");
    file1 >> N;

    for (int i = 0; i < N; i++)
        file1 >> input;
        m3.test(input);
    
    file1.close();

    ofstream file2;
    file2.open("output.txt");
    file2 << m3.getMax();
    file2.close();
    return 0;

代码稍微复杂一些,但程序大小只有 35 KB,几乎没有动态分配。

【讨论】:

【参考方案4】:

用一种向量 1 'V1'(按降序排列)替换 'for' 循环后,程序比较乘积 'V1[0] * V1[1] * V1[2]' 和 'V1[ 0] * V1[N] * V1[N - 1',然后在文件output.txt中打印最大值:

#include <vector>
#include <fstream>
#include <iostream>
#include <algorithm>
#include <functional>

using namespace std;

int main()

    int N;
    long long max = -9223372036854775807;
    int input;

    vector<long long> V1;

    ifstream file1;
    file1.open("input.txt");
    file1 >> N;

    V1.resize(N);

    for (int i = 0; i < N; i++)
        file1 >> V1[i];
    

    sort(V1.begin(), V1.end(), greater<int>());

    N -= 1;

    max = V1[0] * V1[1] * V1[2];

    if (max < V1[0] * V1[N] * V1[N - 1])
        max = V1[0] * V1[N] * V1[N - 1];

    ofstream file2;
    file2.open("output.txt");
    file2 << max;
    file2.close();

【讨论】:

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

Firebase 的 Cloud Functions 因超出内存限制而被终止

超出 sysconfig 限制的共享内存大小

JavaScript 内存不足错误:超出 UDF 线程内存限制-Snowflake

在 Clickhouse 中运行非常简单的查询时超出内存限制

AutoCAD 的设计自动化 - 超出了进程内存限制

PBS vmem 超出限制:我怎么知道内存超出了哪里?