1. 這題感覺真的很難, 首先求和的方法轉換爲前綴和的形式,避免重複計算.想求[i,j]區間則爲sum[i+1]-sum[j].
2. 運用單調雙端隊列解決應該選擇哪個區間的問題.因爲如果存在負數,則需要把包含負數區間的求和去掉,因爲負數後面的數肯定也符合條件>=K,而且長度也比較小.
class Solution {
public:
int shortestSubarray(vector<int>& A, int K) {
if(A.size()==0) return -1;
//定義A.size()+1長度的數組,包含sum[0].
//解決sum[1]=sum[0]+A[0]情況.
//前綴和sum[i]代表[0,i-1]區間的求和.
vector<int> sum(A.size()+1, 0);
deque<int> dq;
int res = INT_MAX;
for(int i=1;i<=A.size();i++) {
sum[i] = sum[i-1]+A[i-1];
}
//單調雙端隊列保證單增,如果存在小於等於的情況,
//說明裏面一定包含負數或0,去掉dq最後一個值.
//從dq最前尋找符合>=K條件的長度,並計算最短長度.
for(int i=0;i<=A.size();i++) {
if(i!=0) {
while(dq.size()>0 && sum[dq.back()]>=sum[i]) dq.pop_back();
while(dq.size()>0 && sum[i]-sum[dq.front()]>=K) {
res = min(res, i-dq.front());
dq.pop_front();
}
}
dq.push_back(i);
}
//有可能不存在,則返回-1.
return res==INT_MAX ? -1:res;
}
};