zoukankan      html  css  js  c++  java
  • Leetcode: Range Sum Query 2D

    Given a 2D matrix matrix, find the sum of the elements inside the rectangle defined by its upper left corner (row1, col1) and lower right corner (row2, col2).
    
    Range Sum Query 2D
    The above rectangle (with the red border) is defined by (row1, col1) = (2, 1) and (row2, col2) = (4, 3), which contains sum = 8.
    
    Example:
    Given matrix = [
      [3, 0, 1, 4, 2],
      [5, 6, 3, 2, 1],
      [1, 2, 0, 1, 5],
      [4, 1, 0, 1, 7],
      [1, 0, 3, 0, 5]
    ]
    
    sumRegion(2, 1, 4, 3) -> 8
    update(3, 2, 2)
    sumRegion(2, 1, 4, 3) -> 10
    Note:
    The matrix is only modifiable by the update function.
    You may assume the number of calls to update and sumRegion function is distributed evenly.
    You may assume that row1 ≤ row2 and col1 ≤ col2.

    参考:https://leetcode.com/discuss/72685/share-my-java-2-d-binary-indexed-tree-solution

    Build binary indexed tree takes :   O(mn*logm*logn)   time, both update() and getSum() take:      O(logm*logn)   time. The arr[][] is used to keep a backup of the matrix[][] so that we know the difference of the updated element and use that to update the binary indexed tree. The idea of calculating sumRegion() is the same as in Range Sum Query 2D - Immutable.

    Summary of Binary Indexed Tree:

    Binary Index Tree参见:https://www.youtube.com/watch?v=CWDQJGaN1gY

    Compare Segment Tree vs Binary Indexed Tree

    Segment Tree:

          Time: O(N)build, O(logN)search, O(logN) update,   space: O(NlogN)

    Binary Indexed Tree:

          Time: O(NlogN)build, O(logN) search, O(logN) update,   space: O(N)

    The advantage of Binary Indexed Tree over Segment Tree are:

    require less space and very easy to implement

     1 public class Solution {
     2       int m, n;
     3       int[][] arr;    // stores matrix[][]
     4       int[][] BITree; // 2-D binary indexed tree
     5 
     6       public Solution(int[][] matrix) {
     7         if (matrix.length == 0 || matrix[0].length == 0) {
     8             return;
     9         }
    10 
    11         m = matrix.length;
    12         n = matrix[0].length;
    13 
    14         arr = new int[m][n];
    15         BITree = new int[m + 1][n + 1];
    16 
    17         for (int i = 0; i < m; i++) {
    18           for (int j = 0; j < n; j++) {
    19             update(i, j, matrix[i][j]); // init BITree[][]
    20  
    21           }
    22         }
    23       }
    24 
    25       public void update(int i, int j, int val) {
    26         int diff = val - arr[i][j];  // get the diff
    27         arr[i][j] = val;             // update arr[][]
    28 
    29         i++; j++;
    30         for (int x=i; x<=m; x+=x&(-x)) {
    31             for (int y=j; y<=n; y+=y&(-y)) {
    32                 BITree[x][y] += diff;
    33             }
    34         }
    35       }
    36 
    37       int getSum(int i, int j) {
    38         int sum = 0;
    39 
    40         i++; j++;
    41         for (int x=i; x>0; x-=x&(-x)) {
    42             for (int y=j; y>0; y-=y&(-y)) {
    43                 sum += BITree[x][y];
    44             }
    45         }
    46         return sum;
    47       }
    48 
    49       public int sumRegion(int i1, int j1, int i2, int j2) {
    50         return getSum(i2, j2) - getSum(i1-1, j2) - getSum(i2, j1-1) + getSum(i1-1, j1-1);
    51       }
    52       

    Introduction from GeeksforGeeks:

    We have an array arr[0 . . . n-1]. We should be able to
    1 Find the sum of first i elements.
    Update value of a specified element of the array arr[i] = x where 0 <= i <= n-1.

    simple solution is to run a loop from 0 to i-1 and calculate sum of elements. To update a value, simply do arr[i] = x. The first operation takes O(n) time and second operation takes O(1) time. Another simple solution is to create another array and store sum from start to i at the i’th index in this array. Sum of a given range can now be calculated in O(1) time, but update operation takes O(n) time now. This works well if the number of query operations are large and very few updates.

    Can we perform both the operations in O(log n) time once given the array? 
    One Efficient Solution is to use Segment Tree that does both operations in O(Logn) time.

    Using Binary Indexed Tree, we can do both tasks in O(Logn) time. The advantages of Binary Indexed Tree over Segment are, requires less space and very easy to implement..

    Representation
    Binary Indexed Tree is represented as an array. Let the array be BITree[]. Each node of Binary Indexed Tree stores sum of some elements of given array. Size of Binary Indexed Tree is equal to n where n is size of input array. In the below code, we have used size as n+1 for ease of implementation.(index 0 is a dummy node)

    Construction
    We construct the Binary Indexed Tree by first initializing all values in BITree[] as 0. Then we call update() operation for all indexes to store actual sums, update is discussed below.

    Operations

    getSum(index): Returns sum of arr[0..index]
    // Returns sum of arr[0..index] using BITree[0..n].  It assumes that
    // BITree[] is constructed for given array arr[0..n-1]
    1) Initialize sum as 0 and index as index+1.
    2) Do following while index is greater than 0.
    ...a) Add BITree[index] to sum
    ...b) Go to parent of BITree[index].  Parent can be obtained by removing
         the last set bit from index, i.e., index = index - (index & (-index))
    3) Return sum.

    BITSum

    
    

    The above diagram demonstrates working of getSum(). Following are some important observations.

    Node at index 0 is a dummy node.

    A node at index y is parent of a node at index x, iff y can be obtained by removing last set bit from binary representation of x.

    A child x of a node y stores sum of elements from of y(exclusive y) and of x(inclusive x).

    update(index, val): Updates BIT for operation arr[index] += val
    // Note that arr[] is not changed here.  It changes
    // only BI Tree for the already made change in arr[].
    1) Initialize index as index+1.
    2) Do following while index is smaller than or equal to n.
    ...a) Add value to BITree[index]
    ...b) Go to next node of BITree[index].  Next node can be obtained by i.e., index = index + (index & (-index))

  • 相关阅读:
    JAVA 使用 POI进行读取Excel表格示例
    问题解决:Maven execution terminated abnormally (exit code 1)
    oracle总结: INTERVAL DAY TO SECOND, 但却获得 NUMBER
    SpringMvc返回JSON出现"$.result.currentLevel"
    Spring+SpringMVC+mybatis maven pom文件
    redis在Linux上的安装
    Jsoup访问https网址异常SSLHandshakeException(已解决)
    不同版本2.5的Servlet web.xml 头信息
    Spring管理事物两种方式
    Error:too many padding sections on bottom border.
  • 原文地址:https://www.cnblogs.com/EdwardLiu/p/5138208.html
Copyright © 2011-2022 走看看