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:

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.

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