307. Range Sum Query - Mutable
Given an integer array nums, find the sum of the elements between indices i and j (i ≤ j), inclusive.
The update(i, val) function modifies nums by updating the element at index i to val.
Example:
Given nums = [1, 3, 5]
sumRange(0, 2) -> 9
update(1, 2)
sumRange(0, 2) -> 8
Note:
- The array is only modifiable by the update function.
- You may assume the number of calls to update and sumRange function is distributed evenly.
My Solution:
class Segment_tree:
def build_Segment_tree(self, pos, left, right, value, nums):
if left == right:
value[pos] = nums[left]
return
mid = (left + right) // 2
self.build_Segment_tree(2 * pos + 1, left, mid, value, nums)
self.build_Segment_tree(2 * pos + 2, mid + 1, right, value, nums)
value[pos] = value[2 * pos + 1] + value[2 * pos + 2]
def sumRange_Segment_tree(self, pos, left, right, qleft, qright, value, nums):
if qleft <= left and qright >= right: # 区间被[qleft, qright]所覆盖
return value[pos]
if qleft > right or qright < left:
return 0
mid = (left + right) // 2
return self.sumRange_Segment_tree(pos * 2 + 1, left, mid, qleft, qright, value, nums) + self.sumRange_Segment_tree(pos * 2 + 2, mid + 1, right, qleft, qright, value, nums)
def update__Segment_tree(self, pos, i, left, right, value, val, nums):
if left == right and left == i:
# if pos == i:
# value[pos] = val
# else:
value[pos] = val
return
mid = (left + right) // 2
if i <= mid:
self.update__Segment_tree(2 * pos + 1, i, left, mid, value, val, nums)
else:
self.update__Segment_tree(2 * pos + 2, i, mid + 1, right, value, val, nums)
value[pos] = value[2 * pos + 1] + value[2 * pos + 2]
class NumArray:
def __init__(self, nums):
"""
:type nums: List[int]
"""
self.value = [0 for i in range(4 * len(nums))] # 线段树通常开数组长度 n 的 4 倍空间4 * n
self.nums = nums
if self.nums:
Segment_tree().build_Segment_tree(0, 0, len(nums) - 1, self.value, self.nums)
def update(self, i, val):
"""
:type i: int
:type val: int
:rtype: void
"""
Segment_tree().update__Segment_tree(0, i, 0, len(self.nums) - 1, self.value, val, self.nums)
def sumRange(self, i, j):
"""
:type i: int
:type j: int
:rtype: int
"""
return Segment_tree().sumRange_Segment_tree(0, 0, len(self.nums) - 1, i, j, self.value, self.nums)
# Your NumArray object will be instantiated and called as such:
# obj = NumArray(nums)
# obj.update(i,val)
# param_2 = obj.sumRange(i,j)
Reference 1:
说明:
Use self.c to represent Binary Indexed Tree.
Section sums are stored in self.c[1..len(nums)]. x & -x is lowbit function,
which will return x's rightmost bit 1, e.g. lowbit(7) = 1, lowbit(20) = 4.
self.c[1] = nums[0]
self.c[2] = nums[0] + nums[1]
self.c[3] = nums[2]
self.c[4] = nums[0] + nums[1] + nums[2] + nums[3]
self.c[5] = nums[4]
self.c[6] = nums[4] + nums[5]
self.c[7] = nums[6]
self.c[8] = nums[0] + nums[1] + nums[2] + nums[3] + nums[4] + nums[5] + nums[6] + nums[7]
class NumArray(object):
def __init__(self, nums):
self.n = len(nums)
self.a, self.c = nums, [0] * (self.n + 1)
for i in range(self.n):
k = i + 1
while k <= self.n:
self.c[k] += nums[i]
k += (k & -k)
def update(self, i, val):
diff, self.a[i] = val - self.a[i], val
i += 1
while i <= self.n:
self.c[i] += diff
i += (i & -i)
def sumRange(self, i, j):
res, j = 0, j + 1
while j:
res += self.c[j]
j -= (j & -j)
while i:
res -= self.c[i]
i -= (i & -i)
return res
Reference 2:
class NumArray(object):
def __init__(self, nums):
self.update = nums.__setitem__
self.sumRange = lambda i, j: sum(nums[i:j+1])
网友评论