327. count-of-range-sum
阿新 • • 發佈:2018-12-19
這道題難度還是挺大的,基本上hard的題目都要費點腦子,根據一般的辦法,求和並暴力的複雜度是O(N^2),而題目中明確說O(N^2)是naive,所以,該題目的難點在於如何降低時間複雜度。
題目大意:給定一組數和一個區間,求改組數中所有滿足該區間加和的子陣列的個數,就是從陣列中挑選一組連續的數,如果選出的數之和滿足條件,則視為一組有效數,如果不滿足條件,則為無效,求所有有效陣列的個數。
思路是,假設建立一個sums陣列,sums[i]表示陣列中前i個數據之和,挑選從j到i之間的陣列,表示為sums[i]-sums[j],而該陣列要滿足lower <= sums[i]-sums[j] <= upper,sums[i]是我們當前遍歷到的最遠位置,sum[j]是已經遍歷過的位置,所以,已經存在於陣列中,而sum[i]是剛算出來的固定值,所以,只要在原來的sums陣列中找到滿足一定條件的sums[j],則j-i一定滿足條件。原式是lower <= sums[i]-sums[j] <= upper,則sums[i]-upper <= sums[j] <= sums[i]-lower。
有了以上的分析思路就明確了,從0開始遍歷,當遍歷到陣列中前i個值之和時,只要判斷sums陣列中,前i 個值中有幾個滿足sums[i]-upper <= sums[j] <= sums[i]-lower(j<i)即可,將結果不斷累加,最終得到的就是所有滿足條件的情況個數。
以下是AC程式碼:
class Solution { public: int countRangeSum(vector<int>& nums, int lower, int upper) { int res = 0; multiset<long long> numset; numset.insert(0); long long sum = 0; for (int i=0; i<nums.size(); ++i) { sum += nums[i]; res += distance(numset.lower_bound(sum-upper), numset.upper_bound(sum-lower)); numset.insert(sum); } return res; } };