307-range-sum-query-mutable¶
Try it on leetcode
Description¶
Given an integer array nums
, handle multiple queries of the following types:
- Update the value of an element in
nums
. - Calculate the sum of the elements of
nums
between indicesleft
andright
inclusive whereleft <= right
.
Implement the NumArray
class:
NumArray(int[] nums)
Initializes the object with the integer arraynums
.void update(int index, int val)
Updates the value ofnums[index]
to beval
.int sumRange(int left, int right)
Returns the sum of the elements ofnums
between indicesleft
andright
inclusive (i.e.nums[left] + nums[left + 1] + ... + nums[right]
).
Example 1:
Input ["NumArray", "sumRange", "update", "sumRange"] [[[1, 3, 5]], [0, 2], [1, 2], [0, 2]] Output [null, 9, null, 8] Explanation NumArray numArray = new NumArray([1, 3, 5]); numArray.sumRange(0, 2); // return 1 + 3 + 5 = 9 numArray.update(1, 2); // nums = [1, 2, 5] numArray.sumRange(0, 2); // return 1 + 2 + 5 = 8
Constraints:
1 <= nums.length <= 3 * 104
-100 <= nums[i] <= 100
0 <= index < nums.length
-100 <= val <= 100
0 <= left <= right < nums.length
- At most
3 * 104
calls will be made toupdate
andsumRange
.
Solution(Python)¶
class NumArray:
def __init__(self, nums: List[int]):
self.ds = Bits(nums)
def update(self, index: int, val: int) -> None:
self.ds.update(index, val)
def sumRange(self, left: int, right: int) -> int:
return self.ds.sumRange(left, right)
class NaiveNumArray:
# Time Complexity: O(n)
def __init__(self, nums: List[int]):
self.nums = nums
# Time Complexity: O(1)
def update(self, index: int, val: int) -> None:
self.nums[index] = val
# Time Complexity: O(n)
def sumRange(self, left: int, right: int) -> int:
return sum(self.nums[left: right+1])
class PresumNumArray:
# Time Complexity: O(n)
def __init__(self, nums: List[int]):
self.n = len(nums)
self.nums = nums
self.presum = [0] * (1 + self.n)
self.build()
def build(self):
for i in range(self.n):
self.presum[i+1] += self.presum[i] + self.nums[i]
# Time Complexity: O(n)
def update(self, index: int, val: int) -> None:
diff = val - self.nums[index]
for i in range(index + 1, self.n):
self.presum[i+1] += diff
self.nums[index] = val
# Time Complexity: O(1)
def sumRange(self, left: int, right: int) -> int:
if left == right:
return self.nums[left]
return self.presum[right + 1] - self.presum[left]
class SegmentTree:
# Time Complexity: O(n)
def __init__(self, nums: List[int]):
self.n = len(nums)
self.tree = [0] * (2*self.n)
self.build(nums)
def build(self, nums):
i = self.n
j = 0
while i< 2*self.n:
self.tree[i] = nums[j]
i += 1
j += 1
for i in range(self.n - 1, -1 ,-1):
self.tree[i] = self.tree[i*2] + self.tree[i*2 + 1]
# Time Complexity: O(log(n))
def update(self, index: int, val: int) -> None:
index += self.n
self.tree[index] = val
while index > 0:
left = index
right = index
if index % 2 == 0:
right = index + 1
else:
left = index - 1
self.tree[index//2] = self.tree[left] + self.tree[right]
index //= 2
# Time Complexity: O(log(n))
def sumRange(self, left: int, right: int) -> int:
left += self.n
right += self.n
s = 0
while left <= right:
if left %2 == 1:
s += self.tree[left]
left += 1
if right % 2 == 0:
s += self.tree[right]
right -= 1
left //=2
right //=2
return s
class Bits:
# Time Complexity: O(nlogn)
def __init__(self, nums: List[int]):
self.nums = nums
self.n = len(nums)
self.tree = [0]*(self.n+1)
for i in range(self.n):
self.build(i, nums[i])
def build(self, i, val):
i += 1
while i<=self.n:
self.tree[i] += val
i += i & (-i)
# Time Complexity: O(log(n))
def update(self, index: int, val: int) -> None:
diff = val - self.nums[index]
self.nums[index] = val
self.build(index, diff)
# Time Complexity: O(log(n))
def sumRange(self, left: int, right: int) -> int:
return self.sum(right) - self.sum(left-1)
def sum(self, i):
s = 0
i += 1
while i>0:
s += self.tree[i]
i -= i & (-i)
return s
# Your NumArray object will be instantiated and called as such:
# obj = NumArray(nums)
# obj.update(index,val)
# param_2 = obj.sumRange(left,right)