思路
思路一
看到這種題,我們首先想到的就是暴力解法,雙層循環遍歷,求出對應的值,與最大值進行比較即可。
過程如下:
-
數據聲明
(1)最大分數,用於比較和返回結果
(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)保存當前最大分數的變量rst
(2)數組長度len,用於判斷循環結束條件
(3)保存當前A[i]+i的最大值的變量max_score -
從下標1開始遍歷數組,求出以當前元素爲j元素時,得分的最大值,並以此更新rst(最初max_score的最大值爲下標爲0時的A[i]+i),同時需要通過當前元素更新max_score
-
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的最大值。