青训营X豆包MarsCode 技术训练营 刷题 环形数组中的最大贡献值 | 豆包MarsCode AI 刷题

23 阅读3分钟

问题理解

题目要求我们在一个环形数组中找到一对下标 (i, j),使得它们的贡献值 f(i, j) = (a_i + a_j) × dist(i, j) 最大。其中 dist(i, j) 是下标 ij 在数组中的最短距离。环形数组的特点是数组的首尾相连,即最左和最右的元素也是相邻的。

数据结构选择

由于题目涉及的是一个数组,我们不需要额外引入复杂的数据结构。数组本身已经足够支持我们进行必要的操作。

算法步骤

  1. 初始化最大贡献值

    • 我们需要一个变量 res 来记录当前找到的最大贡献值,初始值设为0。
  2. 遍历所有可能的下标对 (i, j)

    • 由于数组是环形的,我们需要考虑所有可能的下标对。对于每个下标 i,我们需要遍历所有 j 使得 j > i
  3. 计算贡献值

    • 对于每一对 (i, j),我们需要计算 (a_i + a_j) × dist(i, j)

    • dist(i, j) 的计算需要考虑环形数组的特性:

      • 如果 ji 的右边,dist(i, j) 就是 j - i
      • 如果 ji 的左边(即环形数组的另一侧),dist(i, j) 就是 n - j + i
    • 因此,dist(i, j) 应该是 Math.min(j - i, n - j + i)

  4. 更新最大贡献值

    • 每次计算完一对 (i, j) 的贡献值后,我们需要将其与当前的最大贡献值 res 进行比较,并更新 res
  5. 返回结果

    • 遍历完所有可能的下标对后,res 中存储的就是最大贡献值,直接返回即可。

时间复杂度分析

  • 由于我们需要遍历所有可能的下标对 (i, j),时间复杂度为 O(n^2),其中 n 是数组的长度。
  • 对于每个下标对 (i, j),计算贡献值的时间复杂度为 O(1)

空间复杂度分析

  • 我们只使用了常数级别的额外空间(如 res 变量),因此空间复杂度为 O(1)

优化思路

  • 虽然当前算法的时间复杂度已经是 O(n^2),但对于较大的 n,这个复杂度可能仍然不够理想。

  • 可以考虑使用一些优化技巧,例如:

    • 预处理:预先计算一些中间结果,减少重复计算。
    • 动态规划:尝试使用动态规划的思想,减少不必要的计算。
    • 双指针:如果数组中存在某些规律,可以尝试使用双指针等技巧来减少遍历次数。
public class Main {
    public static int solution(int n, int[] a) {
        // write code here
        int res = 0;
        for(int i=0; i<a.length; i++){
            for(int j=i+1; j<a.length; j++){
                int tmp = (a[i]+a[j])*Math.min(j-i,n-j+i);
                res = Math.max(tmp,res);
            }
        }
        return res; // Placeholder return
    }


    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);
    }
}

总结

通过上述步骤,我们可以有效地找到环形数组中最大贡献值的下标对。虽然当前算法的时间复杂度为 O(n^2),但对于大多数情况已经足够。如果需要进一步优化,可以考虑使用预处理、动态规划或双指针等技巧。