327. 區間和的個數
阿新 • • 發佈:2020-10-25
給定一個整數陣列nums,返回區間和在[lower, upper]之間的個數,包含lower和upper。
區間和S(i, j)表示在nums中,位置從i到j的元素之和,包含i和j(i ≤ j)。
說明:
最直觀的演算法複雜度是O(n2) ,請在此基礎上優化你的演算法。
示例:
輸入: nums = [-2,5,-1], lower = -2, upper = 2,
輸出: 3
解釋: 3個區間分別是: [0,0], [2,2], [0,2],它們表示的和分別為: -2, -1, 2。
class Solution { public: //字首和 sum[i...j]=pre[j]-pre[i] c++ set是有序的 int countRangeSum(vector<int>& nums, int lower, int upper) { vector<long> preSum; long sum = 0; for(int i=0;i<nums.size();i++){ sum += nums[i]; preSum.push_back(sum); } int res=0; multiset<long> pre; pre.insert(0); for(int i=0;i<preSum.size();i++){ // if(preSum[i]>= lower && preSum[i]<=upper){ // res++; // } // for(int j=i+1;j<preSum.size();j++){ // //這裡找preSum[i]的過程導致兩層迴圈。 // //lower <= preSum[j]-preSum[i] <= upper // // preSum[j]-upper =< preSum[i] <= preSum[j]-lower // //查詢: preSum[i] 大於某個數,小於某個數的個數,若是有序陣列,可以使用二分查詢。 // // // // if(preSum[j]-preSum[i]>=lower && preSum[j]-preSum[i]<=upper ){ // // res++; // // } // } //遇到的每一個i,都找他之前的(0-i-1)個數中 位於(當前數-upper)=< preSum[i]<=(當前-lower) 之間得數的個數 //若是之前的0-i-1個數是有序的 //那麼如果S陣列是 有序的 我們就可以通過兩次二分查詢計算出有多少個x滿足條件(d2-d1): //第一次二分查詢找出第一個大於等於 presum - upper 的位置d1; //第二次二分查詢找出第一個大於 presum - lower 的位置d2。 //如何快速保證每次(0-i-1)的字首和陣列都有序?將前(0-i-1)位置的數都存入multiset,利用紅黑樹 auto low = pre.lower_bound(preSum[i]-upper); auto high = pre.upper_bound(preSum[i]-lower); res += distance(low,high); pre.insert(preSum[i]); } return res; } };