环形数组中的最大贡献值
问题描述
小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) 最大。贡献值的计算公式为:
其中 dist(i, j) 是下标 i 和 j 在数组中的最短距离。由于数组是环形的,最短距离可以通过以下公式计算:
解题思路
1. 理解环形数组的特性
环形数组的关键在于理解其边界条件。数组的第一个元素和最后一个元素是相邻的,这意味着在计算距离时,我们需要考虑两种情况:
- 直接计算两个下标之间的距离。
- 通过数组的环形特性计算距离。
例如,对于数组 [1, 2, 3],下标 0 和 2 之间的距离可以是 2 - 0 = 2,也可以是 3 - 2 + 0 = 1(环形距离)。
2. 暴力解法
最直接的解法是使用暴力枚举。我们可以遍历所有可能的下标对 (i, j),计算它们的贡献值,并记录最大值。具体步骤如下:
- 初始化一个变量
maxContribution用于存储最大贡献值。 - 使用两层循环遍历所有下标对
(i, j),其中i和j不能相同。 - 计算
dist(i, j)并根据公式计算贡献值。 - 更新
maxContribution。
这种方法的时间复杂度为 O(n^2),对于较大的 n 可能会导致性能问题。
3. 优化思路
为了优化算法,我们可以考虑以下几点:
- 预处理数组:可以预先计算每个元素与其他元素的距离,减少重复计算。
- 利用对称性:由于
f(i, j) = f(j, i),我们可以减少一半的计算量。 - 动态规划:通过动态规划的思想,记录中间结果,减少重复计算。
4. 代码实现
以下是基于暴力解法的Java代码实现:
public class Main {
public static int solution(int n, int[] a) {
int maxContribution = 0; // 初始化最大贡献值
// 遍历所有可能的下标对 (i, j)
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (i != j) { // 确保 i 和 j 不是同一个下标
// 计算 i 和 j 之间的最短距离(环形数组)
int dist = Math.min(Math.abs(i - j), n - Math.abs(i - j));
// 计算贡献值
int contribution = (a[i] + a[j]) * dist;
// 更新最大贡献值
maxContribution = Math.max(maxContribution, contribution);
}
}
}
return maxContribution; // 返回最大贡献值
}
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);
}
}
5. 进一步优化
虽然暴力解法可以解决问题,但在实际应用中,我们可能需要考虑更高效的算法。例如,可以使用动态规划来减少重复计算,或者通过预处理数组来加速距离的计算。
总结
环形数组问题是一个经典的算法问题,通过理解数组的环形特性,我们可以设计出有效的算法来解决这类问题。暴力解法虽然简单,但在处理大规模数据时可能会遇到性能瓶颈。通过优化算法,我们可以提高程序的效率,使其能够处理更大规模的数据。
在实际编程中,我们还需要考虑边界条件和异常情况,确保代码的健壮性。通过不断练习和优化,我们可以更好地掌握这类问题的解决方法,提升自己的编程能力。