给定正整数数组 A
,A[i]
表示第 i
个观光景点的评分,并且两个景点 i
和 j
之间的距离为 j - i
。
一对景点(i < j
)组成的观光组合的得分为(A[i] + A[j] + i - j
):景点的评分之和减去它们两者之间的距离。
返回一对观光景点能取得的最高分。
示例:
输入:[8,1,5,2,6]
输出:11
解释:i = 0, j = 2, A[i] + A[j] + i - j = 8 + 5 + 0 - 2 = 11
提示:
2 <= A.length <= 50000
1 <= A[i] <= 1000
解题思路
这个问题和之前问题Leetcode 121:买卖股票的最佳时机(最详细的解法!!!)非常类似。只不过我们这里的sell
和buy
重新思考。我们最后需要将A[i] + A[j] + i - j
最大化,也就可以理解为A[i]+i
和A[j]-j
最大化。那么此时的buy
就可以理解为buy=max(buy, A[i]+i)
,而sell
可以理解为sell=max(sell, A[j]-j+buy)
。
最后思考边界问题,我们只需要将sell=0
而buy=float("-inf")
即可。
class Solution:
def maxScoreSightseeingPair(self, A: List[int]) -> int:
sell, buy = 0, float('-inf')
for i, val in enumerate(A):
sell = max(sell, val - i + buy)
buy = max(buy, val + i)
return sell
注意上面的写法,为什么不是这样呢?
buy = max(buy, val + i)
sell = max(sell, val - i + buy)
注意的一个细节就是j>i
,也就是先有j
再有i
,那么我们就需要将sell
放到buy
的前面(我们之前的问题是先buy
后sell
)。
还有一种非常棒的思路,我们每次遍历A
中的元素a
,对于我们遍历过的元素我们当然知道谁是最大的。例如,[8,1,5,2,6]
,我们遍历到8
,我们当然知道8
是那个最大的,接着我们会找第二个数。当我们遍历到1
的时候,此时8
,距离我们的位置就变成1
,也就是说8
会变成7
,此时我们的和就是1+7
,是不是最大的和呢?不知道,还要继续遍历下去。接着找到5
,此时8
距离5
是2
,所以8
变成了6
,所以此时的和就变成了6+5=1
。就这样依次遍历下去,直到所有元素都找完。
class Solution:
def maxScoreSightseeingPair(self, A: List[int]) -> int:
cur = res = 0
for a in A:
res = max(res, cur + a)
cur = max(cur, a) - 1
return res
reference:
https://leetcode.com/problems/best-sightseeing-pair/discuss/260850/JavaC%2B%2BPython-One-Pass
我将该问题的其他语言版本添加到了我的GitHub Leetcode
如有问题,希望大家指出!!!