|
| 1 | +# Time: O(nlogn) |
| 2 | +# Space: O(n) |
| 3 | + |
| 4 | +# Given an integer array nums, return the number of range |
| 5 | +# sums that lie in [lower, upper] inclusive. |
| 6 | +# Range sum S(i, j) is defined as the sum of the elements |
| 7 | +# in nums between indices i and j (i <= j), inclusive. |
| 8 | +# |
| 9 | +# Note: |
| 10 | +# A naive algorithm of O(n^2) is trivial. You MUST do better than that. |
| 11 | +# |
| 12 | +# Example: |
| 13 | +# Given nums = [-2, 5, -1], lower = -2, upper = 2, |
| 14 | +# Return 3. |
| 15 | +# The three ranges are : [0, 0], [2, 2], [0, 2] and |
| 16 | +# their respective sums are: -2, -1, 2. |
| 17 | + |
| 18 | +# Divide and Conquer solution. |
| 19 | +class Solution(object): |
| 20 | + def countRangeSum(self, nums, lower, upper): |
| 21 | + """ |
| 22 | + :type nums: List[int] |
| 23 | + :type lower: int |
| 24 | + :type upper: int |
| 25 | + :rtype: int |
| 26 | + """ |
| 27 | + def countAndMergeSort(sums, start, end, lower, upper): |
| 28 | + if end - start <= 1: # The size of range [start, end) less than 2 is always with count 0. |
| 29 | + return 0 |
| 30 | + mid = start + (end - start) / 2 |
| 31 | + count = countAndMergeSort(sums, start, mid, lower, upper) + \ |
| 32 | + countAndMergeSort(sums, mid, end, lower, upper); |
| 33 | + j, k, r = mid, mid, mid |
| 34 | + tmp = [] |
| 35 | + for i in xrange(start, mid): |
| 36 | + # Count the number of range sums that lie in [lower, upper]. |
| 37 | + while k < end and sums[k] - sums[i] < lower: |
| 38 | + k += 1 |
| 39 | + while j < end and sums[j] - sums[i] <= upper: |
| 40 | + j += 1 |
| 41 | + count += j - k |
| 42 | + |
| 43 | + # Merge the two sorted arrays into tmp. |
| 44 | + while r < end and sums[r] < sums[i]: |
| 45 | + tmp.append(sums[r]) |
| 46 | + r += 1 |
| 47 | + tmp.append(sums[i]) |
| 48 | + # Copy tmp back to sums. |
| 49 | + sums[start:start+len(tmp)] = tmp |
| 50 | + return count |
| 51 | + |
| 52 | + sums = [0] * (len(nums) + 1) |
| 53 | + for i in xrange(len(nums)): |
| 54 | + sums[i + 1] = sums[i] + nums[i] |
| 55 | + return countAndMergeSort(sums, 0, len(sums), lower, upper); |
0 commit comments