【问题标题】: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 个整数而不是整个向量来存储最大数量。
  • 那么你应该更新你的描述。描述类型表明程序必须将结果存储在向量中。但是现在您已经将要求更改为:找到最大值。那是两个非常不同的程序。 :-)

标签: c++ algorithm vector


【解决方案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();
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多