leetcode 907. Sum of Subarray Minimums
阿新 • • 發佈:2019-01-06
leetcode 907. Sum of Subarray Minimums
題目大意
- 將陣列劃分為若干個子陣列(子陣列必須是連續的幾個數),每個子陣列都取數組裡面最小值。求這些最小值的和
###思路
- 首先應該先明確這題的解題思路一定是算每個數的貢獻次數,因為每個數至少有一次機會成為最小值(只有它本身的時候)
- 算一個數的貢獻次數,其實就是看它在多大的範圍內是這範圍內的最小值,舉個簡單例子,3 1 2 4 這4個數,如果我知道了 1 這個數,它能成為最小值的範圍是從0 到 3(因為下標從0開始),那麼你如何計算它的貢獻次數?? 其實非常簡單,1 這個數,可以和左邊的3組合,也可以分別和右邊的 2,(2,4)組合,所以貢獻次數就是(左邊個數+1)(右邊個數+1) 2
- 知道了如何計算,下面的問題就是求出一個數的影響範圍就行。思路很簡單,單調棧就行。不知道單調棧的可以百度。
- 注意一個細節,那就是重複元素的問題,比如 1 1 1 1 這4個數,你的範圍給如何確定? 你可以規定一個方向,向左不能有重複元素,向右可以取等就行。這主要是涉及單調棧的知識,這裡不再細講。
###程式碼
#include <bits/stdc++.h> using namespace std; class Solution { public: typedef long long ll; const int mod=1e9+7; int sumSubarrayMins(vector<int>& A) { int f[30005],g[30005]; int n= A.size(); stack<int> sta; memset(f,-1,sizeof(f)); for(int i=0;i<n;i++) { g[i]=n; } for(int i=0;i<n;i++) { while(sta.empty()==0&&A[sta.top()]>A[i]) { sta.pop(); } if(sta.empty()==0) { f[i]=sta.top(); } sta.push(i); } while(sta.empty()==0) sta.pop(); for(int i=n-1;i>=0;i--) { while(sta.empty()==0&&A[sta.top()]>=A[i]) { sta.pop(); } if(sta.empty()==0) { g[i]=sta.top(); } sta.push(i); } ll ans=0; for(int i=0;i<n;i++) { ans=(ans+(i-f[i])*(g[i]-i)*A[i])%mod; } return ans; } };