[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:

  1. The array is only modifiable by the update function.
  2. 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  */

 

posted @ 2015-11-19 16:25  `Liok  阅读(1284)  评论(0编辑  收藏  举报