数组-最佳观光组合(力扣1014)

题目链接 点我

数组-最佳观光组合(力扣1014)_第1张图片

思路

思路一

看到这种题,我们首先想到的就是暴力解法,双层循环遍历,求出对应的值,与最大值进行比较即可。
过程如下:

  1. 数据声明
    (1)最大分数,用于比较和返回结果
    (2)数组的长度,用于循环条件

  2. 双层循环,第一层循环从0开始,到len-1结束,第二层循环从1开始到len结束
    每次循环计算出目标值与最大值进行比较更新

代码
class Solution {
     
public:
    int maxScoreSightseeingPair(vector<int>& A) {
     
        int maxScore = 0;
        int len = A.size();
        for(int i=0;i<len-1;i++) {
     
            for(int j=i+1;j<len;j++) {
     
                maxScore = max(maxScore, A[i]+A[j]+i-j);
            }
        }
        return maxScore;
    }
};

很明显,时间复杂度是O(n^2),题目肯定不会这么简单地通过地,果然提交后会超时。

思路二

碰到这种多层循环的题我们要想办法转换成更少的循环层数,仔细分析要计算的值为A[i]+i+A[j]-j,我们可以针对每一个A[j]-j,求出以j为结束时,其的最大值,这时候我们只需要找到A[i]+i的最大值即可,因为i在j前面,如果我们j从1开始遍历的话,每次遍历的过程中就可以更新得到j前面A[i]+i的最大值,不用再一次遍历。

过程:

  1. 数据声明
    (1)保存当前最大分数的变量rst
    (2)数组长度len,用于判断循环结束条件
    (3)保存当前A[i]+i的最大值的变量max_score

  2. 从下标1开始遍历数组,求出以当前元素为j元素时,得分的最大值,并以此更新rst(最初max_score的最大值为下标为0时的A[i]+i),同时需要通过当前元素更新max_score

  3. rst即为结果

代码
class Solution {
     
public:
    int maxScoreSightseeingPair(vector<int>& A) {
     
        int rst = 0;
        int len = A.size();
        int max_score = A[0] + 0;
        for(int i=1;i<len;i++) {
     
            rst = max(rst, max_score+A[i] - i);
            max_score = max(max_score, A[i] + i);
        }
        return rst;
    }
};

很明显此时时间复杂度变为了O(n)

总结

1、对于双层循环暴力解法一定要想办法将双层循环变成单层循环
2、对于双层循环求多个元素最大值的问题(是有一定的重复),我们可以通过求元素较少时的最大值,然后不断更新最大值,比如求一个数组中两个元素和的最大值,不能使用排序,我们可以双层循环,但是也可以通过最大值的另一种求法变成单层循环。本题中,双层循环其实是,以每个i为参考点,求j的最大值,然而在求j的最大值过程中,由于元素很多,避免不了有很多重复的过程,然而优化成单层循环是以每个j为参考点,将j的下标压缩到较小位置,求i的最大值,这个时候,我们就能在更新j的过程中同时更新j之前i的最大值。

你可能感兴趣的:(数组,leetcode,算法)