【发布时间】:2021-06-07 16:08:15
【问题描述】:
问题很简单。给定 N (3 12 + 7 + 2。最大算术级数之间的整数不必相邻,并且它们出现的顺序无关紧要。
一个示例输入是:
6
1 6 11 2 7 12
其中第一个数字是 N(在本例中为 6),第二行是长度为 N 个整数的序列。
输出将是任何 3 整数算术级数的最大和。像这样:
21
因为2、7、12是序列中任意3整数算术级数之和最大的数,且2 + 7 + 12 = 21。也保证序列中存在3整数算术级数。
编辑:构成总和(输出)的数字必须是一个算术级数(常数差),长度为 3 个整数。在样本输入的情况下,(1 6 11) 是可能的算术级数,但它小于 (2 7 12),因为 2 + 7 + 12 > 1 + 6 + 11。因此将输出 21,因为它是更大。
这是我用 C++ 解决这个问题的尝试:
#include <bits/stdc++.h>
using namespace std;
vector<int> results;
vector<int> middle;
vector<int> diff;
int main(){
int n;
cin >> n;
int sizes[n];
for (int i = 0; i < n; i++){
int size;
cin >> size;
sizes[i] = size;
}
sort(sizes, sizes + n, greater<int>());
for (int i = 0; i < n; i++){
for (int j = i+1; j < n; j++){
int difference = sizes[i] - sizes[j];
diff.insert(diff.end(), difference);
middle.insert(middle.end(), sizes[j]);
}
}
for (size_t i = 0; i < middle.size(); i++){
int difference = middle[i] - diff[i];
for (int j = 0; j < n; j++){
if (sizes[j] == difference) results.insert(results.end(), middle[i]);
}
}
int max = 0;
for (size_t i = 0; i < results.size(); i++) {
if (results[i] > max) max = results[i];
}
int answer = max * 3;
cout << answer;
return 0;
}
我的方法是使用单独的向量记录中间数字和差异,然后循环遍历向量并搜索中间数字减去差异是否在数组中,然后将其添加到另一个向量。然后找到最大的中间数并乘以 3 得到总和。这种方法使我的算法从 O(n^3) 变为大约 O(n^2)。但是,该算法并不总是每次都能产生正确的输出(而且我想不出一个不起作用的测试用例),并且由于我使用的是单独的向量,所以我得到一个 std::bad_alloc 错误大 N 值,因为我可能使用了太多内存。本题时间限制为每个测试用例 1.4 秒,内存限制为 64 MB。
由于 N 最多只能为 3000,因此 O(n^2) 就足够了。那么这个问题的最优 O(n^2) 解决方案(或更好)是什么?
【问题讨论】:
-
那么就是说你需要选择的3个数字需要相邻?
-
您应该能够在
O(N)时间内完成此操作。取元素 0、1、2,求和,存储为最大值。然后获取元素 1、2 和 3,得到总和,与最大值进行比较。如果它更高,则将 max 设置为该新值并记录起始位置。重复直到你到达最后三个元素。 -
那么如果它们不必相邻,那么简单地选择 3 个最大的数不是问题吗?
-
@StarMan 您对自相矛盾的要求。如果元素不必相邻,那么为什么
11 7 12不是最大和? -
arithmetic progression 或算术级数是一个成熟的数学概念。