這一題我看到數據范圍是10^4,暗自竊喜能用雙重循環,看題目是典型的前綴和+哈希。不過需要一個轉換將大于8小時的轉化為1,其他都為-1,方便計算,之前的題目中也有這種方法。
那這樣就簡單了
class Solution {
public:int sum[100005];
unordered_map<int,int> mp;int longestWPI(vector<int>& hours) {for(int i=0;i<hours.size();i++){if(hours[i]>8)sum[i+1]=sum[i]+1;elsesum[i+1]=sum[i]-1;}int ans=0;mp[0]=0;for(int j=1;j<=hours.size();j++){for(auto it=mp.begin();it!=mp.end();it++){if(sum[j]-(it->first)>0){ans=max(ans,j-it->second);}}mp[sum[j]]=j;}return ans;}
};
這樣是正常的前綴和+哈希,會出現錯誤
因為我們在枚舉的過程中遇到一個前綴和就更新哈希表,這會導致相同的前綴和值它的索引往后放,也就會導致在計算子數組的長度時會變小,因此我們需要做的就是在遇到相同的值的時候不要更新哈希表即可。
正確代碼如下:
class Solution {
public:int sum[100005];
unordered_map<int,int> mp;int longestWPI(vector<int>& hours) {for(int i=0;i<hours.size();i++){if(hours[i]>8)sum[i+1]=sum[i]+1;elsesum[i+1]=sum[i]-1;}int ans=0;mp[0]=0;for(int j=1;j<=hours.size();j++){for(auto it=mp.begin();it!=mp.end();it++){if(sum[j]-(it->first)>0){ans=max(ans,j-it->second);}}if(!mp.count(sum[j]))mp[sum[j]]=j;}return ans;}
};
時間復雜度為O(n^2)雖然輕松通過,但不是最優解
最優解需要我們領會sum取1和0的時候不用再像其他情況一樣,算子數組
而是只要sum>0,那么子數組的長度最長就是j 因為存在sum[0]=0
所以我們可以分情況討論
當sum>0的時候,可以直接更新ans
當sum<=0的時候,我們需要從哈希表中取出 sum-1的值
為啥非要取sum-1,因為sum【j】-sum【i】=子數組,所以必須sum【i】 必須比sum[j]要小.
那為啥不取其他比sum【j】的值呢,因為該前綴和在求的過程中是一步一步變小或者變大的,比如如果sum[j]=-2,那么sum=-1的索引一定在它左邊,也就是說更小的前綴和在右邊,而sum-1在構成子數組和為》0的所有情況中,構成的子數組的長度最大,因為它在最左邊。
所以我們就可以寫代碼了,還要注意遇到相同的值的時候不要更新哈希表。
class Solution {
public:int sum[100005];
unordered_map<int,int> mp;int longestWPI(vector<int>& hours) {for(int i=0;i<hours.size();i++){if(hours[i]>8)sum[i+1]=sum[i]+1;elsesum[i+1]=sum[i]-1;}int ans=0;mp[0]=0;for(int j=1;j<=hours.size();j++){if(sum[j]>0){ans=max(ans,j);}else{if(mp.count(sum[j]-1)){ans=max(ans,j-mp[sum[j]-1]);}}if(!mp.count(sum[j])){mp[sum[j]]=j;}}return ans;}
};
時間復雜度為O(n)為最優解。