题目描述
思路解析动画文字版
记住「拆成 (values[i]+i)+(values[j]−j),扫 j 维护左边最大的 values[i]+i」,下面每帧都在套它。
开局把第 0 个景点作为左端候选:bestLeft = values[0]+0 = 8(绿色标出当前最佳左端)。从 j=1 开始,每个 j 都拿 bestLeft 来配对。
右端点走到第 1 个(评分 1)。配上左边最佳端点(绿色,下标 0):得分 8 + 1 − 1 = 8。比旧的最大得分更高,刷新 ans=8。
第 1 个作为左端候选只有 values[1]+1 = 2,没超过 bestLeft=8,最佳左端不动,绿色仍停在下标 0。
右端点走到第 2 个(评分 5)。配上左边最佳端点(绿色,下标 0):得分 8 + 5 − 2 = 11。比旧的最大得分更高,刷新 ans=11。
第 2 个作为左端候选只有 values[2]+2 = 7,没超过 bestLeft=8,最佳左端不动,绿色仍停在下标 0。
右端点走到第 3 个(评分 2)。配上左边最佳端点(绿色,下标 0):得分 8 + 2 − 3 = 7。没超过当前最大 ans=11,保持。
第 3 个作为左端候选只有 values[3]+3 = 5,没超过 bestLeft=8,最佳左端不动,绿色仍停在下标 0。
右端点走到第 4 个(评分 6)。配上左边最佳端点(绿色,下标 0):得分 8 + 6 − 4 = 10。没超过当前最大 ans=11,保持。
再把第 4 个也纳入「左端候选」:values[4]+4 = 10,比旧的 bestLeft 大,于是最佳左端(绿色)移到下标 4,bestLeft=10。后面的 j 会用这个更优的左端。
右端点走到第 5 个(评分 7)。配上左边最佳端点(绿色,下标 4):得分 10 + 7 − 5 = 12。比旧的最大得分更高,刷新 ans=12。
再把第 5 个也纳入「左端候选」:values[5]+5 = 12,比旧的 bestLeft 大,于是最佳左端(绿色)移到下标 5,bestLeft=12。后面的 j 会用这个更优的左端。
右端点走到第 6 个(评分 3)。配上左边最佳端点(绿色,下标 5):得分 12 + 3 − 6 = 9。没超过当前最大 ans=12,保持。
第 6 个作为左端候选只有 values[6]+6 = 9,没超过 bestLeft=12,最佳左端不动,绿色仍停在下标 5。
右端点走到第 7 个(评分 9)。配上左边最佳端点(绿色,下标 5):得分 12 + 9 − 7 = 14。比旧的最大得分更高,刷新 ans=14。
再把第 7 个也纳入「左端候选」:values[7]+7 = 16,比旧的 bestLeft 大,于是最佳左端(绿色)移到下标 7,bestLeft=16。后面的 j 会用这个更优的左端。
右端点走到第 8 个(评分 4)。配上左边最佳端点(绿色,下标 7):得分 16 + 4 − 8 = 12。没超过当前最大 ans=14,保持。
第 8 个作为左端候选只有 values[8]+8 = 12,没超过 bestLeft=16,最佳左端不动,绿色仍停在下标 7。
右端点走到第 9 个(评分 10)。配上左边最佳端点(绿色,下标 7):得分 16 + 10 − 9 = 17。比旧的最大得分更高,刷新 ans=17。
再把第 9 个也纳入「左端候选」:values[9]+9 = 19,比旧的 bestLeft 大,于是最佳左端(绿色)移到下标 9,bestLeft=19。后面的 j 会用这个更优的左端。
扫完全程,最优是绿色这一对:下标 7(评分 9)和下标 9(评分 10),得分 9+10+7−9 = 17。一遍扫描、不回头就锁定了答案。
边界先想清:两元素只有一对;递减时越靠前越好。
两个追问,核心是认出「前缀最优 + 一遍扫描」这个母题。
参考代码
from typing import Listclass Solution: def maxScoreSightseeingPair(self, values: List[int]) -> int: best_left = values[0] ans = -10**18 for j in range(1, len(values)): ans = max(ans, best_left + values[j] - j) best_left = max(best_left, values[j] + j) return ans复杂度
- 时间:O(n),只扫一遍
- 空间:O(1),只用 bestLeft、ans 两个变量
易错点
面试追问把动画讲成自己的话
追问这题和「买卖股票 LC121」像在哪?
追问如果要求返回最优的两个下标怎么办?
这道题到这就讲完了。动画和文字是同一套思路——别光看,关掉页面自己默写一遍。然后顺着主线继续:
最长等差数列
LeetCode 1027 · 中等 · 沿着 动态规划套路 继续往下推进
把这道题真正学会,再走
图解算法年卡 ¥99 /年
- ✓本题每步动画的吴师兄语音讲解(全站陆续覆盖)
- ✓小欧带 8 步通关训练——追问到不看答案也能写对、能 30 秒讲给面试官听
- ✓学习报告,记录每道题的掌握程度
76k+ GitHub Star · 吴师兄开源图解算法,几十万开发者在看的算法讲解
想成体系刷透这类套路?去图解算法专题