forked from shuboc/LeetCode-2
-
Notifications
You must be signed in to change notification settings - Fork 1
/
count-of-range-sum.py
97 lines (87 loc) · 3.43 KB
/
count-of-range-sum.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
# Time: O(nlogn)
# Space: O(n)
# Given an integer array nums, return the number of range
# sums that lie in [lower, upper] inclusive.
# Range sum S(i, j) is defined as the sum of the elements
# in nums between indices i and j (i <= j), inclusive.
#
# Note:
# A naive algorithm of O(n^2) is trivial. You MUST do better than that.
#
# Example:
# Given nums = [-2, 5, -1], lower = -2, upper = 2,
# Return 3.
# The three ranges are : [0, 0], [2, 2], [0, 2] and
# their respective sums are: -2, -1, 2.
# Divide and Conquer solution.
class Solution(object):
def countRangeSum(self, nums, lower, upper):
"""
:type nums: List[int]
:type lower: int
:type upper: int
:rtype: int
"""
def countAndMergeSort(sums, start, end, lower, upper):
if end - start <= 1: # The size of range [start, end) less than 2 is always with count 0.
return 0
mid = start + (end - start) / 2
count = countAndMergeSort(sums, start, mid, lower, upper) + \
countAndMergeSort(sums, mid, end, lower, upper)
j, k, r = mid, mid, mid
tmp = []
for i in xrange(start, mid):
# Count the number of range sums that lie in [lower, upper].
while k < end and sums[k] - sums[i] < lower:
k += 1
while j < end and sums[j] - sums[i] <= upper:
j += 1
count += j - k
# Merge the two sorted arrays into tmp.
while r < end and sums[r] < sums[i]:
tmp.append(sums[r])
r += 1
tmp.append(sums[i])
# Copy tmp back to sums.
sums[start:start+len(tmp)] = tmp
return count
sums = [0] * (len(nums) + 1)
for i in xrange(len(nums)):
sums[i + 1] = sums[i] + nums[i]
return countAndMergeSort(sums, 0, len(sums), lower, upper)
# Divide and Conquer solution.
class Solution2(object):
def countRangeSum(self, nums, lower, upper):
"""
:type nums: List[int]
:type lower: int
:type upper: int
:rtype: int
"""
def countAndMergeSort(sums, start, end, lower, upper):
if end - start <= 0: # The size of range [start, end] less than 2 is always with count 0.
return 0
mid = start + (end - start) / 2
count = countAndMergeSort(sums, start, mid, lower, upper) + \
countAndMergeSort(sums, mid + 1, end, lower, upper)
j, k, r = mid + 1, mid + 1, mid + 1
tmp = []
for i in xrange(start, mid + 1):
# Count the number of range sums that lie in [lower, upper].
while k <= end and sums[k] - sums[i] < lower:
k += 1
while j <= end and sums[j] - sums[i] <= upper:
j += 1
count += j - k
# Merge the two sorted arrays into tmp.
while r <= end and sums[r] < sums[i]:
tmp.append(sums[r])
r += 1
tmp.append(sums[i])
# Copy tmp back to sums
sums[start:start+len(tmp)] = tmp
return count
sums = [0] * (len(nums) + 1)
for i in xrange(len(nums)):
sums[i + 1] = sums[i] + nums[i]
return countAndMergeSort(sums, 0, len(sums) - 1, lower, upper)