原题截图
题意分析
原题题意分析
本题的题意较为简单,即有一个数组,对于所有的,找出的最大值。
题意修改
按照原题的题意,因为且题目没有规定如果找不到任何一对景点输出什么值,所以本题不应出现数组大小为的情况。但经过实测,本题的测试数据中含有数组大小为的数据(如下图)。
所以原题的题意和测试数据出现矛盾,在不改变测试数据的前提下,必须修改题意才能使题目逻辑正确。一种可行的修改方案为,规定找不到任何一对景点时输出,按照此方案修改后的题意如下:
有一个数组,对于所有的,输出的最大值;如果没有任何一对满足,输出。
解题思路
本题容易想到复杂度为的解法,即用两层循环暴力遍历每一对的组合,并计算的值。但稍微多加思考,即可发现本题也可用时间复杂度更低的的算法来解决,即遍历时记录的最大值,然后在后续遍历中将遍历到的数视为,得出的值,然后直接使用已经记录的的最大值,得出的最大值,即可节省一层循环,这种解法实际上使用了类似动态规划的记忆化思想。
具体解法为,如果values的大小为1,直接返回0。否则,定义变量ansmax记录答案的最大值,变量imax记录的最大值。然后将这两个变量的初值设为一个已知必定会在后续遍历中取到的值(在本题中即为某一对或某一个景点的相应值),具体来说,将ansmax的初值设为values[0] + values[1] - 1(即当时的值),imax的初值设为values[0](即当时的值)。从第2个数开始遍历数组,设遍历到的值为i,对于每一个i,首先更新ansmax = max(ansmax, values[i]-i+imax);,然后更新imax = max(imax, values[i]+i);(这种更新顺序保证了更新ansmax的值时,imax的值一定不会包括i本身,从而保证了)。遍历完成后,ansmax的值即为答案。
代码实现
#include <bits/stdc++.h>
using namespace std;
int solution(std::vector<int> values)
{
if(values.size() == 1) return 0;
int imax=values[0], ansmax=values[0]+values[1]-1;
int n=values.size();
for(int i=1;i<n;i++)
{
ansmax = max(ansmax, values[i]-i+imax);
imax = max(imax, values[i]+i);
}
return ansmax;
}
总结
本题使用类似动态规划的记忆化方法解决,设数组的长度为,本题的时间复杂度为,空间复杂度为,如果你有复杂度更优的解法,欢迎在下方评论。