问题描述
小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
分析思路
首先,我们需要理解环形数组的特点,即数组的首尾元素是相邻的。这意味着在计算两个下标之间的距离时,我们需要考虑两种情况:一种是直接距离,另一种是通过数组首尾相连的距离。具体来说,对于任意两个下标 ( i ) 和 ( j ),它们的距离可以表示为 {dist}(i, j) = min(|j - i|, n - |j - i|) 。
为了找到最大贡献值,我们需要遍历数组中的所有可能的下标对 ( (i, j) ),计算每一对的贡献值,并记录其中的最大值。由于环形数组的特性,我们需要特别注意数组的边界情况。
解题步骤
- 初始化变量:定义一个变量 res 来存储最大贡献值,初始值为0。
- 遍历数组:使用两个嵌套的循环遍历数组中的所有下标对
( (i, j) )。外层循环从0遍历到( n-1 ),内层循环从1遍历到( n )。 - 计算距离:对于每一对下标
( (i, j) ),计算它们的两种可能的距离:直接距离和通过数组首尾相连的距离 。取这两者的最小值作为最终距离。 - 计算贡献值:根据公式,计算当前下标对的贡献值。
- 更新最大值:如果当前贡献值大于
res,则更新res。 - 返回结果:遍历结束后,返回
res作为最大贡献值。
具体代码
public static int solution(int n, int[] a) {
int res = 0;
for (int i = 0; i < n - 1; i++) {
for (int j = 1; j < n; j++) {
int dist1 = (j - i);
int dist2 = (n - j + i);
int dist = Math.min(dist1, dist2);
int newres = (a[i] + a[j]) * dist;
if (newres > res) {
res = newres;
}
}
}
return res;
}
public static void main(String[] args) {
System.out.println(solution(3, new int[] { 1, 2, 3 }) == 5);
System.out.println(solution(4, new int[] { 4, 1, 2, 3 }) == 12);
System.out.println(solution(5, new int[] { 1, 5, 3, 7, 2 }) == 24);
}
}
总结
与普通数组不同,环形数组的首尾相连特性增加了计算距离的复杂性。通过对距离的两种情况进行比较,我们能够准确计算出最短距离,从而确保贡献值的计算是正确的。