907. 子陣列的最小值之和
阿新 • • 發佈:2018-12-10
給定一個整數陣列 A
,找到 min(B)
的總和,其中 B
的範圍為 A
的每個(連續)子陣列。
由於答案可能很大,因此返回答案模 10^9 + 7
。
示例:
輸入:[3,1,2,4] 輸出:17 解釋: 子陣列為 [3],[1],[2],[4],[3,1],[1,2],[2,4],[3,1,2],[1,2,4],[3,1,2,4]。 最小值為 3,1,2,4,1,1,2,1,1,1,和為 17。
提示:
1 <= A <= 30000
1 <= A[i] <= 30000
解答如下:(這題對問題進行復雜度優化,是解決問題的關鍵,一個是統計相同數值的個數,進行了一次優化,其次是計算針對一個數值為尾的N個子陣列的最小值的和,利用上次結果,進行第二次優化;否則將執行超時)
class Solution { public: int sumSubarrayMins(vector<int>& A) { int size=A.size(); //dp[i]為以當前位置為尾,以前面某個數字為首,其最小值為i的的個數, //這裡用map,利用紅黑樹的特性,可以進行log(2,n)的快速查詢 map<int,long long> dp; long long result=0;//這裡是總結果 long long temp=0;//這裡是針對某個數值A[n],其前邊A[n];A[n-1],A[n];...;A[0]...A[n]的最小值的和 for(int i=0;i<size;i++){ //若不存在當前數值,則以該數值本身構成的子陣列個數為1 if(dp.find(A[i])==dp.end()){ dp[A[i]]=1; }else{ //若存在,則以該數字為最小值的dp[A[i]]+1 dp[A[i]]+=1; } //新增一個數,其本身作為子陣列,需要計入當前數值temp中 temp+=A[i]; //這裡利用upper_bound(),用log(2,n)的時間複雜度查詢到比他大元素迭代器 for(map<int,long long>::iterator iter= dp.upper_bound(A[i]);iter!=dp.end();){ //因為A[i]作為尾,所以比他大的都要降級,即減少(iter->first-A[i])*iter->second temp-=(iter->first-A[i])*iter->second; dp[A[i]]+=iter->second;//由於減少到A[i],所以需要將數量併入dp[A[i]] dp.erase(iter++);//因為降級,所以不存在了。這裡iter++的用法十分巧妙 //答主用dp.erase(iter); //然後用iter--(因為後面的iter++在for迴圈中); 再iter++,居然出現異常,無法刪除最後一個元素 //糾錯卡了半天 } result=(temp+result)%(1000000000 + 7); } return result; } };