zoukankan      html  css  js  c++  java
  • LeetCode 307. Range Sum Query

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

  • 相关阅读:
    OCP-1Z0-053-V12.02-69题
    OCP-1Z0-053-V12.02-170题
    OCP-1Z0-053-V12.02-117题
    OCP-1Z0-053-V12.02-222题
    OCP-1Z0-053-V12.02-528题
    OCP-1Z0-053-V12.02-531题
    OCP-1Z0-053-V12.02-532题
    OCP-1Z0-053-V12.02-533题
    OCP-1Z0-053-V12.02-542题
    OCP-1Z0-053-V12.02-68题
  • 原文地址:https://www.cnblogs.com/Dylan-Java-NYC/p/5139205.html
Copyright © 2011-2022 走看看