Range Sum Query - Mutable
MediumArrayDesignBinary Indexed TreeSegment Tree
Solution
class Node {
start: number;
end: number;
total: number;
left: Node | null;
right: Node | null;
constructor(start: number, end: number) {
this.start = start;
this.end = end;
this.total = 0;
this.left = null;
this.right = null;
}
}
export class NumArray {
private readonly root: Node | null;
constructor(nums: number[]) {
this.root = this.createTree(nums, 0, nums.length - 1);
}
private createTree(nums: number[], start: number, end: number): Node | null {
if (start > end) {
return null;
}
if (start === end) {
const node = new Node(start, end);
node.total = nums[start];
return node;
}
const mid = Math.floor((start + end) / 2);
const node = new Node(start, end);
node.left = this.createTree(nums, start, mid);
node.right = this.createTree(nums, mid + 1, end);
node.total = (node.left?.total ?? 0) + (node.right?.total ?? 0);
return node;
}
private _update(node: Node | null, i: number, value: number): void {
if (node === null) {
return;
}
if (node.start === node.end) {
node.total = value;
return;
}
const mid = Math.floor((node.start + node.end) / 2);
if (i <= mid) {
this._update(node.left, i, value);
} else {
this._update(node.right, i, value);
}
node.total = (node.left?.total ?? 0) + (node.right?.total ?? 0);
}
private _sumRange(node: Node | null, start: number, end: number): number {
if (node === null) {
return 0;
}
if (node.start === start && node.end === end) {
return node.total;
}
const mid = Math.floor((node.start + node.end) / 2);
if (end <= mid) {
return this._sumRange(node.left, start, end);
}
if (start >= mid + 1) {
return this._sumRange(node.right, start, end);
}
return this._sumRange(node.left, start, mid) + this._sumRange(node.right, mid + 1, end);
}
update(i: number, value: number): void {
this._update(this.root, i, value);
}
sumRange(left: number, right: number): number {
return this._sumRange(this.root, left, right);
}
}