[LeetCode][JavaScript]Range Sum Query - Mutable
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
https://leetcode.com/problems/range-sum-query-mutable/
线段树。
举例来说[2, 4, 6, 8, 10],如图所示建立线段树。
黑色为数组下标,红色是这个线段对应元素的和。
update和sumRange的复杂度都是O(logn)。
建立线段树:
root节点的长度就是入参数组的长度,找出middle,递归建立左子树和右子树。
update操作:
从上往下找到要更新的叶子节点,递归回溯的时候,把祖先的节点的val也一起更新了。
sumRange操作:
找到目标线段,返回val,如果结果分散在左右子树中,分开找到之后相加。
1 /** 2 * @constructor 3 * @param {number[]} nums 4 */ 5 var NumArray = function(nums) { 6 if(nums.length === 0) return; 7 this._root = buildSegment(0, nums.length - 1); 8 9 function buildSegment(start, end){ 10 var currNode = new Node(start, end); 11 if(start === end){ 12 currNode.val = nums[start]; 13 }else{ 14 var middle = parseInt((start + end) / 2); 15 currNode.left = buildSegment(start, middle); 16 currNode.right = buildSegment(middle + 1, end); 17 currNode.val = currNode.left.val + currNode.right.val; 18 } 19 return currNode; 20 } 21 function Node(start, end){ 22 this.start = start; 23 this.end = end; 24 this.val = null; 25 this.left = null; 26 this.right = null; 27 } 28 }; 29 30 /** 31 * @param {number} i 32 * @param {number} val 33 * @return {void} 34 */ 35 NumArray.prototype.update = function(i, val) { 36 updateNum(this._root, i); 37 38 function updateNum(node, i){ 39 if(node.start === node.end && node.start === i){ 40 node.val = val; 41 return node.val; 42 } 43 var middle = parseInt((node.start + node.end) / 2); 44 if(i <= middle){ 45 node.val -= node.left.val; 46 node.val += updateNum(node.left, i); 47 }else{ 48 node.val -= node.right.val; 49 node.val += updateNum(node.right, i); 50 } 51 return node.val; 52 } 53 }; 54 55 /** 56 * @param {number} i 57 * @param {number} j 58 * @return {number} 59 */ 60 NumArray.prototype.sumRange = function(i, j) { 61 return findRange(this._root, i, j); 62 63 function findRange(node, start, end){ 64 if(node.start === start && node.end === end){ 65 return node.val; 66 } 67 var result = 0, middle = parseInt((node.start + node.end) / 2); 68 if(end <= middle){ 69 result += findRange(node.left, start, end); 70 }else if(middle < start){ 71 result += findRange(node.right, start, end); 72 }else{ 73 result += findRange(node.left, start, middle); 74 result += findRange(node.right, middle + 1, end); 75 } 76 return result; 77 } 78 }; 79 80 81 /** 82 * Your NumArray object will be instantiated and called as such: 83 * var numArray = new NumArray(nums); 84 * numArray.sumRange(0, 1); 85 * numArray.update(1, 10); 86 * numArray.sumRange(0, 2); 87 */