问题描述
给定一个数组 values,其中 values[i] 表示第 i 个观光景点的评分。我们需要找到一对景点 (i, j),其中 i < j,使得它们的观光组合得分最大化。观光组合得分的计算公式为:
关键点分析
-
表达式的拆分:
- 观光组合得分公式可以拆分成两部分:
- 这样拆分的好处是可以分别处理
values[i] + i和values[j] - j,从而简化问题。
-
动态更新:
- 我们可以在遍历数组的过程中,动态地更新两个关键变量:
max_i:当前遇到的最大values[i] + i。max_score:当前遇到的最大观光组合得分。
- 我们可以在遍历数组的过程中,动态地更新两个关键变量:
解题步骤
-
初始化:
max_i初始化为values[0] + 0,即第一个景点的评分加上它的下标。max_score初始化为 0,表示当前找到的最大观光组合得分。
-
遍历数组:
- 从第二个元素开始遍历数组(即从
j = 1开始)。 - 对于每个
j:- 计算当前的观光组合得分
current_score = max_i + values[j] - j。 - 更新
max_score为当前的最大值max(max_score, current_score)。 - 更新
max_i为当前的最大值max(max_i, values[j] + j)。
- 计算当前的观光组合得分
- 从第二个元素开始遍历数组(即从
-
返回结果:
- 遍历结束后,
max_score就是最高得分。
- 遍历结束后,
示例解析
让我们通过一个具体的例子来理解这个过程。
示例1:values = [8, 3, 5, 5, 6]
-
初始化:
max_i = 8 + 0 = 8max_score = 0
-
遍历数组:
j = 1:current_score = 8 + 3 - 1 = 10max_score = max(0, 10) = 10max_i = max(8, 3 + 1) = 8
j = 2:current_score = 8 + 5 - 2 = 11max_score = max(10, 11) = 11max_i = max(8, 5 + 2) = 8
j = 3:current_score = 8 + 5 - 3 = 10max_score = max(11, 10) = 11max_i = max(8, 5 + 3) = 8
j = 4:current_score = 8 + 6 - 4 = 10max_score = max(11, 10) = 11max_i = max(8, 6 + 4) = 10
-
返回结果:
max_score = 11
完整代码
def solution(values: list) -> int:
# 初始化 max_i 和 max_score
max_i = values[0] + 0
max_score = 0
# 遍历数组,从第二个元素开始
for j in range(1, len(values)):
# 计算当前的观光组合得分
current_score = max_i + values[j] - j
# 更新最大得分
max_score = max(max_score, current_score)
# 更新 max_i
max_i = max(max_i, values[j] + j)
return max_score
if __name__ == '__main__':
print(solution(values=[8, 3, 5, 5, 6]) == 11)
print(solution(values=[10, 4, 8, 7]) == 16)
print(solution(values=[1, 2, 3, 4, 5]) == 8)
时间和空间复杂度
- 时间复杂度:(O(n)),其中 (n) 是数组的长度,因为我们只需要一次遍历数组。
- 空间复杂度:(O(1)),因为我们只使用了常数级的额外空间。