超出内存限制或时间限制
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.resize
在push_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
的向量,但你读到了int
s。由于您输入的数字很大,因此请在任何地方使用long long
推送一个项目并将其弹回是没有意义的 - 您应该在推送之前检查它以避免两次不必要的操作
无论如何,您根本不需要比较 i
、j
、k
是否相等 - 根据您的循环限制,它们永远不会相等
当您知道项目编号错误时,将项目推送到数组中。扩展向量需要更多时间。您可能希望将其调整为给定大小。
大概,这段代码会满足你的记忆\时间要求:
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 因超出内存限制而被终止
JavaScript 内存不足错误:超出 UDF 线程内存限制-Snowflake