原题链接在这里:https://leetcode.com/problems/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.
题解:
Could use Binary Indexed Tree.
For binary indexed tree:
0001 S1 = A1
0010 S2 = A1+A2
0011 S3 = A3
0100 S4 = A1+A2+A3+A4
0101 S5 = A5
0110 S6 = A5+A6
0111 S7 = A7
1000 S8 = A1+A2+A3+A4+A5+A6+A7+A8
For each binary index, looking for its last digit 1. Then sum or update it moves these steps.
It could be 100, actually last digit 1 here construct number 4. Then its sum, sum already involves previous 4 numbers, like S4.
Update this index only reports to this index +4 number, like change A4, updating S4, then update S8.
更新与求和都能维持O(log n)时间.
Time Complexity: NumArray, O(nlogn). update, O(logn). sumRange, O(logn). n = nums.length.
Space: O(n).
AC Java:
1 public class NumArray { 2 int [] bit; 3 int [] nums; 4 5 public NumArray(int[] nums) { 6 if(nums == null || nums.length == 0){ 7 return; 8 } 9 this.bit = new int[nums.length+1]; 10 this.nums = new int[nums.length]; 11 for(int i = 0; i<nums.length; i++){ 12 update(i, nums[i]); 13 } 14 } 15 16 public void update(int i, int val) { 17 int diff = val - this.nums[i]; 18 this.nums[i] = val; 19 for(int j = i+1; j<this.bit.length; j+=(j&-j)){ 20 this.bit[j] += diff; 21 } 22 } 23 24 public int sumRange(int i, int j) { 25 return getSum(j+1) - getSum(i); 26 } 27 28 private int getSum(int i){ 29 int sum = 0; 30 while(i > 0){ 31 sum += this.bit[i]; 32 i -= (i&-i); 33 } 34 return sum; 35 } 36 } 37 38 /** 39 * Your NumArray object will be instantiated and called as such: 40 * NumArray obj = new NumArray(nums); 41 * obj.update(i,val); 42 * int param_2 = obj.sumRange(i,j); 43 */
Could use Segment Tree.
For segment tree, tree[i] = tree[2*i] + tree[2*i+1]. left child is 2*i, right child is 2*i+1.
When constructing segment tree, tree size is 2*n. n = nums.length. Assign nums value to tree from index n to 2*n-1.
While updating,
find the pos = i+n. For each level, if pos is even number, then it is left child. Its peer pos+1 is the right child.
If pos is odd, it is right child, its peer pos-1 is the left child.
When getting sum,
find the right position l = i+n, r = j+n.
For each left, if l is odd, then it is actually right child of its partent, we only need l part, not its parent, sum += tree[l].
same for r, if r is even, then tis is actually left child of its parent, we only need r part, not its parent. sum += tree[r].
Otherwise we need the parent, this would be got later. Loop while l <= r.
Time Complexity: NumArray, O(n). update, O(logn). sumRange, O(logn). n = nums.length.
Space: O(n).
AC Java:
1 class NumArray { 2 int n; 3 int [] tree; 4 5 public NumArray(int[] nums) { 6 n = nums.length; 7 tree = new int[2*n]; 8 9 for(int i = n, j = 0; i<2*n; i++, j++){ 10 tree[i] = nums[j]; 11 } 12 13 for(int i = n-1; i>0; i--){ 14 tree[i] = tree[2*i]+tree[2*i+1]; 15 } 16 } 17 18 public void update(int i, int val) { 19 int pos = i+n; 20 tree[pos] = val; 21 22 while(pos>0){ 23 int left = pos; 24 int right = pos; 25 if(pos%2 == 0){ 26 right++; 27 }else{ 28 left--; 29 } 30 31 tree[pos/2] = tree[left] + tree[right]; 32 pos /= 2; 33 } 34 } 35 36 public int sumRange(int i, int j) { 37 int l = i+n; 38 int r = j+n; 39 int sum = 0; 40 41 while(l<=r){ 42 if(l%2 == 1){ 43 sum += tree[l]; 44 l++; 45 } 46 47 if(r%2 == 0){ 48 sum += tree[r]; 49 r--; 50 } 51 52 l /= 2; 53 r /= 2; 54 } 55 56 return sum; 57 } 58 } 59 60 /** 61 * Your NumArray object will be instantiated and called as such: 62 * NumArray obj = new NumArray(nums); 63 * obj.update(i,val); 64 * int param_2 = obj.sumRange(i,j); 65 */
类似Range Sum Query - Immutable.
跟上Range Sum Query 2D - Mutable.
Reference: http://www.cnblogs.com/grandyang/p/4985506.html.