环形数组中的最大贡献值-题目解析| 豆包MarsCode AI刷题

93 阅读5分钟

摘要

本文研究了计算环形数组中最大贡献值的问题,其中贡献值定义为两个元素之和与它们之间最短距离的乘积。由于数组是环形的,首尾元素相邻,因此计算最短距离时需考虑环形特性。为了找到使贡献值最大的元素对,本文采用了暴力搜索方法,即遍历数组中所有可能的元素对组合,计算它们的贡献值,并实时更新最大贡献值。虽然该方法直观且易于实现,但时间复杂度较高,为O(n^2)。在代码实现部分,给出了一个完整的Java程序,该程序通过两层循环实现了暴力搜索,并提供了测试用例验证程序的正确性。尽管暴力搜索方法在时间效率上不是最优的,但它为解决问题提供了一个基本框架,为进一步优化提供了基础。在实际应用中,可以考虑使用更高效的算法或数据结构来降低时间复杂度,提高性能。

题目解析

问题描述

小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。

解题思路

题目理解

题目要求在一个长度为 n 的环形数组中,找到一对下标 (i, j),使得它们的贡献值 f(i, j) = (a_i + a_j) × dist(i, j) 最大。其中 dist(i, j) 是下标 i 和 j 在数组中的最短距离。

关键点

  1. 环形数组:数组的首尾相连,即最后一个元素和第一个元素是相邻的。
  2. 最短距离:由于数组是环形的,最短距离可以是 Math.abs(i - j) 或者 n - Math.abs(i - j),取两者中的最小值。

方法思路

  1. 遍历所有可能的 (i, j) 组合:由于数组长度为 n,我们需要遍历所有可能的下标对 (i, j),其中 i 和 j 不能相同。
  2. 计算最短距离 dist(i, j):对于每一对 (i, j),计算它们的最短距离。
  3. 计算贡献值 f(i, j):根据公式 f(i, j) = (a_i + a_j) × dist(i, j) 计算贡献值。
  4. 更新最大贡献值:在每次计算完 f(i, j) 后,更新最大贡献值。

数组结构选择

  • 数组:用于存储输入的高度值。
  • 变量:用于存储当前的最大面积。

图解

假设我们有一个环形数组 [1, 2, 3],我们可以将其展开为:

1 -> 2 -> 3 -> 1

对于每一对下标 (i, j),我们可以计算它们的最短距离:

  • dist(0, 1) = 1
  • dist(0, 2) = 1
  • dist(1, 2) = 1
  • dist(1, 0) = 1
  • dist(2, 0) = 1
  • dist(2, 1) = 1

代码详解

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) {
                    // 计算 dist(i, j)
                    int dist = Math.min(Math.abs(i - j), n - Math.abs(i - j));
                    // 计算 f(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);
    }
}

代码解释

1、遍历所有可能的 (i, j) 组合 2、计算最短距离 dist(i, j) 3、计算贡献值 f(i, j) 4、更新最大贡献值:在每次计算完 f(i, j) 后,更新最大贡献值。

总结

本文深入探讨了计算环形数组中最大贡献值的问题。在这个问题中,我们面对的是一个长度为n的环形数组,目标是找到一对下标(i, j),使得它们的贡献值f(i, j) = (a_i + a_j) × dist(i, j)最大化。其中,dist(i, j)表示下标ij在数组中的最短距离,而环形数组的特性使得首尾元素相邻。

为了解决这个问题,我们采用了暴力搜索的方法。具体来说,我们遍历了数组中所有可能的(i, j)组合,对于每一对组合,都计算了它们的最短距离和贡献值,并实时更新了最大贡献值。这种方法虽然直观且易于实现,但其时间复杂度为O(n^2),在处理大数据集时可能会遇到性能瓶颈。

在代码实现部分,我们给出了一个完整的Java程序,该程序通过两层循环遍历了所有可能的(i, j)组合,并计算了相应的贡献值。同时,我们还提供了几个测试用例来验证程序的正确性。

总的来说,虽然暴力搜索方法在时间复杂度上不是最优的,但它为我们提供了一个解决问题的基本框架。在实际应用中,我们可以根据问题的具体特点,尝试使用更高效的算法或数据结构来优化性能。例如,在这个问题中,我们可以考虑使用动态规划、前缀和或单调栈等技巧来降低时间复杂度。