青训营X豆包MarsCode 技术训练营第四课 | 豆包MarsCode AI 刷题

48 阅读4分钟

题目解析:寻找环形数组中的最大贡献值

题目背景

在计算机科学中,环形数组是一种特殊的数组结构,其特点是数组的第一个元素和最后一个元素是相邻的。这种结构在实际应用中非常常见,例如在时间序列分析、循环队列等场景中。本题要求我们在一个环形数组中找到一对下标 ij,使得它们的贡献值 f(i, j) 最大。

题目描述

给定一个长度为 n 的环形数组 a,定义两个下标 ij 的贡献值公式为: [ f(i, j) = (a_i + a_j) \times \text{dist}(i, j) ] 其中 dist(i, j) 是下标 ij 在数组中的最短距离。我们需要找到一对下标,使得它们的贡献值尽可能大。

测试样例

  • 样例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

解题思路

解决这个问题的关键在于理解环形数组的特性,并计算出任意两个下标之间的最短距离。我们可以通过以下步骤来实现:

  1. 理解环形数组的特性:环形数组的特点是数组的第一个元素和最后一个元素是相邻的。因此,任意两个下标 ij 之间的最短距离可以是 |i - j|n - |i - j|
  2. 计算贡献值:对于每一对下标 ij,计算它们的贡献值 f(i, j),并记录最大值。
  3. 遍历所有可能的下标对:由于数组是环形的,我们需要考虑所有可能的下标对,包括跨越数组边界的情况。

代码实现

public class Main {
    public static int solution(int n, int[] a) {
        int maxContribution = 0;
        for (int i = 0; i < n; i++) {
            for (int j = i + 1; j < n + i; j++) {
                int jIndex = j % n;
                int contribution = (a[i] + a[jIndex]) * Math.min(Math.abs(jIndex - i), n - Math.abs(jIndex - i));
                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);
    }
}

image.png

代码分析

  1. 初始化最大贡献值:我们初始化 maxContribution 为 0。
  2. 遍历所有可能的下标对:使用两层循环遍历所有可能的下标对 (i, j),其中 j 的范围是从 i + 1n + i
  3. 计算贡献值:对于每一对下标 (i, j),计算 jIndex = j % n,然后计算贡献值 contribution,并更新 maxContribution
  4. 返回最大贡献值:遍历结束后,返回 maxContribution

时间复杂度分析

该算法的时间复杂度为 O(n^2),其中 n 是数组的长度。因为我们使用了嵌套循环来遍历所有可能的下标对。

空间复杂度分析

该算法的空间复杂度为 O(1),因为我们只使用了常数个额外的变量来存储最大贡献值和当前贡献值。

个人思考与分析

在解决这个问题时,我们利用了环形数组的特性来计算任意两个下标之间的最短距离。这种方法不仅代码简洁,而且能够在合理的时间内解决问题。

然而,O(n^2) 的时间复杂度在数组长度较大时可能会导致性能问题。为了进一步优化算法,我们可以考虑以下几点:

  1. 优化距离计算:在计算 dist(i, j) 时,我们可以利用对称性来减少计算量。例如,对于每个 i,我们只需要计算 j[i+1, i+n/2] 范围内的贡献值,因为 dist(i, j)dist(j, i) 是对称的。
  2. 使用哈希表:我们可以使用哈希表来存储已经计算过的贡献值,避免重复计算。

总结

通过本文的分析,我们不仅掌握了如何在一个环形数组中找到最大贡献值,还深入理解了环形数组的特性和算法的优化方法。希望这篇文章能够帮助你在算法学习和编程实践中获得更多的启发和思考。

扩展思考

如果数组的长度非常大,如何进一步优化算法以提高性能?这个问题可以通过减少不必要的计算和利用数据结构来解决。具体来说,我们可以使用分治法或动态规划来进一步优化算法。

结论

通过本文的分析,我们不仅掌握了如何在一个环形数组中找到最大贡献值,还深入理解了环形数组的特性和算法的优化方法。希望这篇文章能够帮助你在算法学习和编程实践中获得更多的启发和思考。