AI刷题题解(五) | 豆包MarsCode AI刷题

90 阅读4分钟

环形数组中的最大贡献值之题解

题目概述

小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 的环形数组中找到一对下标 (i, j),使它们的贡献值 f(i, j) = (a_i + a_j) × dist(i, j) 最大。其中 dist(i, j) 是下标 i 和 j 在数组中的最短距离。

考虑需要实现的功能

  1. 遍历所有可能的下标对

    • 使用两层循环遍历所有可能的下标对 (i, j),其中 i 和 j 不能相同。
  2. 计算最短距离

    • 对于每一对 (i, j),计算它们之间的最短距离 dist(i, j)
  3. 计算贡献值

    • 使用公式 (a_i + a_j) × dist(i, j) 计算每一对 (i, j) 的贡献值。
  4. 更新最大贡献值

    • 在遍历过程中,不断更新最大贡献值。

算法步骤

  1. 初始化一个变量 maxContribution 用于存储最大贡献值,初始值为 0。

  2. 使用两层循环遍历所有可能的下标对 (i, j)

    • 如果 i 不等于 j,则计算 dist(i, j)
    • 计算贡献值 contribution = (a_i + a_j) × dist(i, j)
    • 更新 maxContribution 为 max(maxContribution, contribution)
  3. 返回 maxContribution

实现代码

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之间的最短距离
                    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);
    }
}

输出范例

true
true
true

具体运行步骤

  1. 初始化 maxContribution

    • 在 solution 方法中,首先初始化一个变量 maxContribution,用于存储最大贡献值,初始值为 0。
  2. 遍历所有可能的下标对 (i, j)

    • 使用两层循环遍历所有可能的下标对 (i, j)

      • 外层循环 for (int i = 0; i < n; i++) 遍历数组中的每一个元素,i 从 0 到 n-1
      • 内层循环 for (int j = 0; j < n; j++) 遍历数组中的每一个元素,j 从 0 到 n-1
  3. 计算最短距离 dist(i, j)

    • 在内层循环中,首先检查 i 是否等于 j。如果 i 不等于 j,则继续执行以下步骤:1. - - 计算下标 i 和 j 之间的最短距离 dist

      • dist = Math.min(Math.abs(i - j), n - Math.abs(i - j))
      • Math.abs(i - j) 计算 i 和 j 之间的直接距离。
      • n - Math.abs(i - j) 计算从数组末尾绕回到数组开头的情况。
      • Math.min 取两者中的较小值,即为最短距离。
  4. 计算贡献值 f(i, j)

    • 使用公式 (a[i] + a[j]) * dist 计算贡献值 contribution
  5. 更新最大贡献值

    • 使用 Math.max(maxContribution, contribution) 更新 maxContribution,确保 maxContribution 始终存储当前的最大贡献值。
  6. 返回最大贡献值

    • 在遍历完所有可能的下标对后,返回 maxContribution
  7. 测试用例

    • 在 main 方法中,调用 solution 方法并打印结果,验证代码的正确性。

需要注意的tips

  1. 环形数组的特性

    • 数组的首尾是相连的,因此计算两个下标之间的最短距离时,需要考虑两种情况:直接距离和绕回距离。
  2. 贡献值的计算

    • f(i, j) = (a_i + a_j) × dist(i, j)
    • dist(i, j) 是通过 Math.min(Math.abs(i - j), n - Math.abs(i - j)) 计算得到的。
  3. 遍历所有可能的下标对

    • 使用两层循环遍历所有可能的下标对 (i, j),其中 i 和 j 不能相同。

用到的Java方法

  1. Math.min

    • 用于计算两个下标之间的最短距离。
    • 语法:Math.min(a, b),返回 a 和 b 中的较小值。
  2. Math.abs

    • 用于计算两个下标之间的直接距离。
    • 语法:Math.abs(a),返回 a 的绝对值。
  3. Math.max

    • 用于更新最大贡献值。
    • 语法:Math.max(a, b),返回 a 和 b 中的较大值。
  4. for 循环

    • 用于遍历数组中的所有元素。
    • 语法:for (int i = 0; i < n; i++),遍历从 0 到 n-1 的所有下标。