11.观光景点组合得分问题 | 豆包MarsCode AI刷题

124 阅读3分钟

观光景点组合得分问题分析与解题思路

问题理解

给定一个数组values,其中values[i]表示第i个观光景点的评分。我们定义景点之间的距离为它们的下标差j - i,并且一对景点(i < j)的观光组合得分公式为:

css
复制代码
得分 = values[i] + values[j] + (i - j)

目标是找到两景点(i, j),使得得分达到最大值。

得分公式解析

得分公式可以拆解为两部分:

  • 评分部分values[i] + values[j]
  • 距离部分i - j

根据这个公式,我们可以重新表达为:

css
复制代码
得分 = (values[i] - i) + (values[j] + j)

其中,values[i] - ivalues[j] + j是两个独立的部分。这个公式告诉我们:要最大化得分,我们可以分别找到values[i] - ivalues[j] + j的最大值,并组合它们。

优化思路

根据上述分析,我们可以采取以下步骤:

  1. 遍历所有可能的i,计算values[i] - i
  2. 对于每个jj > i),计算values[j] + j
  3. 对于每个j,使用values[i] - i的最大值(从之前的i中获取),并加上values[j] + j,计算得分。

这样,我们就能够在遍历过程中实时更新最大得分,而无需使用两层嵌套循环来检查每一对(i, j)

时间复杂度分析

通过上述优化方法,我们将问题的时间复杂度降低为O(N),其中N是数组values的长度。这样,计算每个j对应的最大得分时,我们只需要一次遍历即可。

代码实现

java
复制代码
public class Main {
    public static int solution(int[] values) {
        if (values == null || values.length < 2) {
            return 0; // 如果数组为空或只有一个元素,无法形成有效的组合
        }

        int maxScore = Integer.MIN_VALUE; // 初始化最大得分
        int maxValue = values[0] - 0; // 初始时,maxValue等于第一个元素的值减去下标0

        // 从第二个元素开始遍历
        for (int j = 1; j < values.length; j++) {
            // 计算当前得分
            int currentScore = values[j] + j + maxValue;
            // 更新最高得分
            maxScore = Math.max(maxScore, currentScore);
            // 更新 maxValue,使得它始终保存前面所有元素的最大值 (values[i] - i)
            maxValue = Math.max(maxValue, values[j] - j);
        }

        return maxScore; // 返回最大得分
    }

    public static void main(String[] args) {
        // 测试用例
        System.out.println(solution(new int[]{8, 3, 5, 5, 6}) == 11 ? 1 : 0); // 11
        System.out.println(solution(new int[]{10, 4, 8, 7}) == 16 ? 1 : 0);  // 16
        System.out.println(solution(new int[]{1, 2, 3, 4, 5}) == 8 ? 1 : 0);  // 8
    }
}

解题过程

  1. 初始化

    • maxScore:用于存储当前找到的最大得分,初始值为Integer.MIN_VALUE
    • maxValue:用于存储前面所有values[i] - i中的最大值,初始值为values[0] - 0
  2. 遍历

    • 对于每个jj > i),计算当前得分:currentScore = values[j] + j + maxValue,其中maxValuei位置之前的最大值values[i] - i
    • 更新maxScore为当前得分与之前得分的最大值。
    • 更新maxValuevalues[j] - j和之前maxValue的较大值,以确保在下次计算时能够使用最大的values[i] - i
  3. 返回最大得分

    • 遍历结束后,maxScore保存的是我们找到的最大得分。

测试样例验证

  1. 输入values = [8, 3, 5, 5, 6]

    • 输出:11
    • 解析:最大得分发生在i=0, j=4时,得分为8 + 6 + (0 - 4) = 11
  2. 输入values = [10, 4, 8, 7]

    • 输出:16
    • 解析:最大得分发生在i=0, j=2时,得分为10 + 8 + (0 - 2) = 16
  3. 输入values = [1, 2, 3, 4, 5]

    • 输出:8
    • 解析:最大得分发生在i=0, j=4时,得分为1 + 5 + (0 - 4) = 8

总结

通过优化,我们将时间复杂度从O(N^2)降低到了O(N),大大提高了效率。在处理较大规模的输入时,这种优化将显著减少计算时间。我们通过维护一个单一的maxValue来避免内层循环的冗余计算,从而提升了程序的执行效率。