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

54 阅读3分钟

问题描述

小R正在研究一组观光景点,每个景点都有一个评分,保存在数组 values 中,其中 values[i] 表示第 i 个观光景点的评分。同时,景点之间的距离由它们的下标差 j - i 表示。

一对景点 (i < j) 的观光组合得分为 values[i] + values[j] + i - j,也就是两者评分之和减去它们之间的距离。

小R想知道,在哪种情况下能够获得观光景点组合的最高得分。


测试样例

样例1:

输入:values = [8, 3, 5, 5, 6]
输出:11

样例2:

输入:values = [10, 4, 8, 7]
输出:16

样例3:

输入:values = [1, 2, 3, 4, 5]
输出:8

问题解析

我们需要找到一个具有最大得分的景点组合,其中得分的计算方式为:

score=values[i]+values[j]+(i−j) =values[i]+values[j]+(i−j)

其中 i 和 j 是两个不同的景点下标,且 i<j 。这意味着我们需要在一对景点之间找到最大得分。

观察与优化

从问题的定义可以看出,我们的目标是最大化这个得分公式:

score=values[i]+values[j]+(i−j)\text{score} = \text{values}[i] + \text{values}[j] + (i - j)score=values[i]+values[j]+(i−j)

我们可以将其拆解成两部分:

  • 第一部分:values[i]−i\text{values}[i] - ivalues[i]−i
  • 第二部分:values[j]+j\text{values}[j] + jvalues[j]+j

这意味着,公式可以变为:

score=(values[i]−i)+(values[j]+j)\text{score} = (\text{values}[i] - i) + (\text{values}[j] + j)score=(values[i]−i)+(values[j]+j)

优化思路

我们可以在遍历过程中维护两个值:

  • max1=values[i]−i\text{max1} = \text{values}[i] - imax1=values[i]−i(第一个景点的得分值)
  • max2=values[j]+j\text{max2} = \text{values}[j] + jmax2=values[j]+j(第二个景点的得分值)

每次计算时,只需要找到目前 max1\text{max1}max1 的最大值和 max2\text{max2}max2 的值的和。这样可以避免我们原本的两层嵌套循环,从而大大提升效率。

算法设计

  1. 初始化:维护 max1 为一个非常小的值(代表第一个景点的得分最大值),max2 为当前景点的值加上其下标。
  2. 遍历数组:从第一个景点到最后一个景点,依次计算每个景点的得分,并更新 max1max2
  3. 返回结果:最终返回最大得分。

代码实现

#include <vector>
#include <iostream>
#include <climits>  // 为了使用INT_MIN

using namespace std;

int solution(vector<int>& values) {
    int maxScore = INT_MIN;  // 用于存储最终的最大得分
    int max1 = INT_MIN;      // 用于存储 values[i] - i 的最大值
    
    // 从第二个元素开始计算最大得分
    for (int j = 1; j < values.size(); ++j) {
        // 计算当前组合的得分
        maxScore = max(maxScore, max1 + values[j] + j);
        
        // 更新 max1 为当前 values[i] - i 的最大值
        max1 = max(max1, values[j - 1] - (j - 1));
    }
    
    return maxScore;
}

int main() {
    // 测试样例
    cout << solution({8, 3, 5, 5, 6}) << endl;  // 输出: 11
    cout << (solution({8, 3, 5, 5, 6}) == 11) << endl;
    cout << (solution({10, 4, 8, 7}) == 16) << endl;
    cout << (solution({1, 2, 3, 4, 5}) == 8) << endl;
    return 0;
}

代码解析

  1. 初始化变量

    • maxScore 用于记录计算过程中的最大得分,初始化为 INT_MIN,表示尚未计算任何得分。
    • max1 用于存储 values[i] - i 的最大值,初始化为 INT_MIN
  2. 遍历计算

    • 从第二个元素开始遍历(即 j = 1),因为 ij 必须满足 i < j
    • 每次计算当前景点 j 与之前景点 i 的得分,更新 maxScore
    • 更新 max1,保持其为 values[i] - i 的最大值。
  3. 返回结果

    • 最后,返回存储的最大得分 maxScore

时间复杂度

  • 该算法仅需要一次遍历整个数组,所以时间复杂度为 O(n) ,其中 nvalues 数组的长度。

空间复杂度

  • 由于只使用了常数级的额外空间,空间复杂度为 O(1)