[M前缀和] lc1014. 最佳观光组合(思维+前缀和+算法优化)
Posted Ypuyu
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[M前缀和] lc1014. 最佳观光组合(思维+前缀和+算法优化)相关的知识,希望对你有一定的参考价值。
1. 题目来源
链接:1014. 最佳观光组合
进阶题:[Mdp] lc1937. 扣分后的最大得分(dp优化+前后缀优化+周赛250_3)
2. 题目解析
思维题,算法优化,两次遍历妥妥超时,也没啥二段性可言,没想到是一次遍历啊。
方法一:
- 简单精心转换:
(A[i]+i)+(A[j]-j)
则可以通过一次顺序遍历,用一个数组maxA[i]
来维护前i
个位置上A[i]+i
的最大值。然后在逆序遍历,用一个变量维护后半段A[j]-j
的最大值,查询maxA[j]
即可知道当前位置上A[i]+i
的最大值,累加,每次更新答案最大值即可。 - 由于需要保证
i<j
,所以针对j
的遍历需要逆向遍历。 - 两次遍历即可找到答案。
- 需要保证
i<j
,故求最值的时候细节需要注意。维护后j
个最大值,前半段最大值是maxA[j - 1]
,
方法二:
- 用一个变量维护前半段
A[i]+i
的最大值,直接和当前的A[j]-j
累加,更新答案,并更新前半段的A[i]+i
的最大值即可。 - 这样一次遍历,就能找到答案。
时间复杂度: O ( n ) O(n) O(n)
空间复杂度: O ( 1 ) O(1) O(1)
方法一:
class Solution {
public:
int maxScoreSightseeingPair(vector<int>& values) {
int n = values.size();
vector<int> maxA(n);
maxA[0] = values[0];
for (int i = 1; i < n; i ++ ) maxA[i] = max(maxA[i - 1], values[i] + i);
int res = -1e9, maxB = -1e9;
for (int i = n - 1; i >= 1; i -- ) {
maxB = max(maxB, values[i] - i);
res = max(res, maxA[i - 1] + maxB);
}
return res;
}
};
其实,如果循环从数组下标 1 开始的话,答案和最值都应该赋一个初始值,例如 for(int i = 0; i < n - 1; i ++ )
这种,当只有一个元素的时候,根本进不去循环,res=-1e9
将直接返回。已经吃了很多次亏了…
class Solution {
public:
int maxScoreSightseeingPair(vector<int>& values) {
int n = values.size();
vector<int> maxA(n);
maxA[0] = values[0];
for (int i = 1; i < n; i ++ ) maxA[i] = max(maxA[i - 1], values[i] + i);
int maxB = values[n - 1] - (n - 1);
int res = maxA[n - 2] + maxB;
for (int i = n - 1; i >= 1; i -- ) {
maxB = max(maxB, values[i] - i);
res = max(res, maxA[i - 1] + maxB);
}
return res;
}
};
方法二:最优解法了
class Solution {
public:
int maxScoreSightseeingPair(vector<int>& values) {
int n = values.size();
int res = -1e9, a = -1e9;
for (int i = 0; i < n; i ++ ) {
res = max(res, a + values[i] - i);
a = max(a, values[i] + i);
}
return res;
}
};
以上是关于[M前缀和] lc1014. 最佳观光组合(思维+前缀和+算法优化)的主要内容,如果未能解决你的问题,请参考以下文章