LeetCode 307. Range Sum Query - Mutable

原题链接在这里: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:

  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.

题解:

Could use Binary Indexed Tree.

For binary indexed tree, for each binary index, looking for its last digit 1. Then supdate it moves these steps to the next one.

e.g. update 0001 means update 0001 + 1 = 0010, means update 0010 + 2 = 0100, menas update 0100 + 4 = 1000.

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

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.

posted @ 2016-01-18 14:40  Dylan_Java_NYC  阅读(363)  评论(0编辑  收藏  举报