Dare2Solve
The NumArray
class is designed to handle two main operations efficiently on a list of integers: updating an element at a specific index and calculating the sum of elements within a given range. The implementation utilizes a Binary Indexed Tree (BIT) to achieve these operations in logarithmic time, making it suitable for scenarios where frequent updates and sum queries are required.
A Binary Indexed Tree (BIT) is an advanced data structure that allows efficient updates and prefix sum calculations. The intuition behind using a BIT is to maintain a tree-like structure where each node stores the cumulative sum of a subset of the array elements. This structure allows both update and sum operations to be performed in (O(\log n)) time, where (n) is the number of elements in the array. The BIT is particularly effective when there are multiple range sum queries and updates, as it significantly reduces the time complexity compared to a naive approach.
BIT Initialization:
BIT
class is initialized with an array size of (N + 1), where (N) is the length of the input array. The additional element accounts for the 1-based indexing required by the BIT operations.Increase Operation:
increase(i, x)
method updates the BIT by adding the value (x) to the (i)-th index and all of its relevant ancestors in the tree. This is done by manipulating the index using the operation i |= (i + 1)
to move to the next relevant node.Total Operation:
total(i)
method calculates the prefix sum from the start of the array to the (i)-th index by traversing the tree from the (i)-th index backward, accumulating the values stored in the relevant nodes.NumArray Class:
NumArray
class initializes the BIT and populates it with the initial values of the input array using the increase
method.update(index, val)
method adjusts the value at a specific index by calculating the difference (delta
) between the new value and the current value, then applying this difference using the BIT's increase
method.sumRange(left, right)
method computes the sum of the elements between the left
and right
indices by utilizing the BIT's total
method to get the prefix sums and subtracting the results accordingly.Both the update and sum range operations run in (O(\log n)) time, where (n) is the number of elements in the array. This efficiency is achieved due to the logarithmic height of the Binary Indexed Tree.
The space complexity is (O(n)) for storing the BIT array, where (n) is the length of the input array. This additional space is required to maintain the tree structure that supports efficient updates and queries.
class BIT {
private:
std::vector<int> stree;
public:
BIT(int N) {
stree = std::vector<int>(N + 1, 0);
}
void increase(int i, int x) {
while (i < stree.size()) {
stree[i] += x;
i |= (i + 1);
}
}
int total(int i) {
int sum = 0;
while (i >= 0) {
sum += stree[i];
i = (i & (i + 1)) - 1;
}
return sum;
}
};
class NumArray {
private:
BIT bit;
std::vector<int> nums;
public:
NumArray(std::vector<int>& nums) : bit(nums.size()), nums(nums) {
for (int i = 0; i < nums.size(); i++) {
bit.increase(i + 1, nums[i]);
}
}
void update(int index, int val) {
int delta = val - nums[index];
bit.increase(index + 1, delta);
nums[index] += delta;
}
int sumRange(int left, int right) {
return bit.total(right + 1) - bit.total(left);
}
};
class BIT:
def __init__(self, N):
self.stree = [0] * (N + 1)
def increase(self, i, x):
while i < len(self.stree):
self.stree[i] += x
i |= (i + 1)
def total(self, i):
sum = 0
while i >= 0:
sum += self.stree[i]
i = (i & (i + 1)) - 1
return sum
class NumArray:
def __init__(self, nums):
self.bit = BIT(len(nums))
self.nums = nums
for i in range(len(nums)):
self.bit.increase(i + 1, nums[i])
def update(self, index, val):
delta = val - self.nums[index]
self.bit.increase(index + 1, delta)
self.nums[index] += delta
def sumRange(self, left, right):
return self.bit.total(right + 1) - self.bit.total(left)
class BIT {
private int[] stree;
public BIT(int N) {
stree = new int[N + 1];
}
public void increase(int i, int x) {
while (i < stree.length) {
stree[i] += x;
i |= (i + 1);
}
}
public int total(int i) {
int sum = 0;
while (i >= 0) {
sum += stree[i];
i = (i & (i + 1)) - 1;
}
return sum;
}
}
class NumArray {
private BIT bit;
private int[] nums;
public NumArray(int[] nums) {
bit = new BIT(nums.length);
this.nums = nums;
for (int i = 0; i < nums.length; i++) {
bit.increase(i + 1, nums[i]);
}
}
public void update(int index, int val) {
int delta = val - nums[index];
bit.increase(index + 1, delta);
nums[index] += delta;
}
public int sumRange(int left, int right) {
return bit.total(right + 1) - bit.total(left);
}
}
class BIT {
constructor(N) {
this.stree = new Array(N+1).fill(0)
}
increase(i, x) {
while(i < this.stree.length) {
this.stree[i] += x
i |= (i+1)
}
}
total(i) {
let sum = 0
while(i >= 0) {
sum += this.stree[i]
i &= i + 1
i -= 1
}
return sum
}
}
var NumArray = function(nums) {
this.bit = new BIT(nums.length)
for(let i = 0; i < nums.length; i++) {
const curr = nums[i]
this.bit.increase(i + 1, curr)
}
this.nums = nums
};
/**
* @param {number} index
* @param {number} val
* @return {void}
*/
NumArray.prototype.update = function(index, val) {
const delta = val - this.nums[index]
this.bit.increase(index + 1, delta)
this.nums[index] += delta
};
NumArray.prototype.sumRange = function(left, right) {
return this.bit.total(right + 1) - this.bit.total(left)
};