问题描述
小S拿到了一个长度为 nn 的环形数组,并定义了两个下标 ii 和 jj 的贡献值公式为:
f(i, j) = (a_i + a_j) × dist(i, j)
其中 dist(i, j) 是下标 ii 和 jj 在数组中的最短距离。小S希望找到一对下标,使得它们的贡献值尽可能大。环形数组的特点是最左和最右的元素也是相邻的。你需要帮助她找到最大贡献值。
例如,给定数组 [1, 2, 3],由于是环形数组,任意两个下标的距离都是1,因此 f(2,3)=(2+3)×1=5f(2,3)=(2+3)×1=5。
测试样例
样例1:
输入:
n = 3,a = [1, 2, 3]
输出:5
样例2:
输入:
n = 4,a = [4, 1, 2, 3]
输出:12
样例3:
输入:
n = 5,a = [1, 5, 3, 7, 2]
输出:24
问题理解
你有一个长度为 n 的环形数组 a,需要找到两个下标 i 和 j,使得 f(i, j) = (a[i] + a[j]) * dist(i, j) 的值最大。其中 dist(i, j) 是下标 i 和 j 在数组中的最短距离。
关键点
-
环形数组:由于数组是环形的,最左和最右的元素也是相邻的。因此,计算距离时需要考虑两种情况:
j在i的右边,距离为j - i。j在i的左边,距离为i + n - j。
-
贡献值公式:
f(i, j) = (a[i] + a[j]) * dist(i, j)。
解题思路
-
遍历所有可能的
i和j组合:- 对于每个
i,遍历j从i+1到n-1,j从i+1开始遍历是为了减少不必要的循环次数。 - 计算
dist(i, j)并更新最大贡献值。
- 对于每个
-
计算距离:
- 对于每个
i和j,计算dist(i, j)为min(j - i, i + n - j)。
- 对于每个
-
更新最大贡献值:
- 使用
max函数更新当前的最大贡献值。
- 使用
数据结构选择
- 使用一个变量
res来存储当前的最大贡献值,循环过程中更新即可。
算法步骤
-
初始化
res为 0:- 这是为了确保在第一次比较时,
res能够被正确更新。
- 这是为了确保在第一次比较时,
-
遍历所有可能的
i和j组合:- 使用两层循环,外层循环遍历
i,内层循环遍历j。 - 注意
j从i+1开始,因为i和j不能相同。
- 使用两层循环,外层循环遍历
-
计算
dist(i, j):- 对于每个
i和j,计算dist(i, j)为min(j - i, i + n - j)。 - 这里
min函数用于选择最短的距离。
- 对于每个
-
更新最大贡献值:
- 使用
max函数更新res,即res = max(res, (a[i] + a[j]) * dist(i, j))。
- 使用
-
返回
res:- 最终返回
res,即最大贡献值。
- 最终返回
代码如下:
#include <iostream>
#include <vector>
#include <string>
using namespace std;
int solution(int n, std::vector<int> a) {
// write code here
int res = 0;
for (int i = 0; i < n; i++) {
for (int j = i + 1; j < n; j++) {
int d = min(j - i, i + n - j);
res = max(res, (a[i] + a[j]) * d);
}
}
return res; // Placeholder return
}
int main() {
std::cout << (solution(3, {1, 2, 3}) == 5) << std::endl;
std::cout << (solution(4, {4, 1, 2, 3}) == 12) << std::endl;
std::cout << (solution(5, {1, 5, 3, 7, 2}) == 24) << std::endl;
return 0;
}