303. Range Sum Query - Immutable && 304. Range Sum Query 2D - Immutable && 307. Range Sum Query - Mutable && 308. Range Sum Query 2D - Mutable

303. Range Sum Query - Immutable

Given an integer array nums, find the sum of the elements between indices i and j (i ≤ j), inclusive.

Example:

Given nums = [-2, 0, 3, -5, 2, -1]

sumRange(0, 2) -> 1
sumRange(2, 5) -> -1
sumRange(0, 5) -> -3

Note:

  1. You may assume that the array does not change.
  2. There are many calls to sumRange function.
Hide Tags
 Dynamic Programming
 
public class NumArray {

    private int[] sums = null;
    
    public NumArray(int[] nums) {
        for(int i =1; i<nums.length; ++i)
        {
            nums[i] += nums[i-1];
        }
        sums = nums;
    }

    public int sumRange(int i, int j) {
        if(i == 0)
            return sums[j];
        return sums[j] - sums[i-1];
    }
}


// Your NumArray object will be instantiated and called as such:
// NumArray numArray = new NumArray(nums);
// numArray.sumRange(0, 1);
// numArray.sumRange(1, 2);

 

304. Range Sum Query 2D - Immutable

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
sumRegion(1, 1, 2, 2) -> 11
sumRegion(1, 2, 2, 4) -> 12 

Note:

  1. You may assume that the matrix does not change.
  2. There are many calls to sumRegion function.
  3. You may assume that row1 ≤ row2 and col1 ≤ col2.
Hide Tags
 Dynamic Programming
 
public class NumMatrix {
  private int[][] sums; //This keeps a sum from (0,0) to (row+1, col+1)

  public NumMatrix(int[][] matrix) {
    if (matrix == null || matrix.length == 0 || matrix[0].length == 0)
      return;

    int row = matrix.length;
    int col = matrix[0].length;

    sums = new int[row + 1][col + 1];
    for (int r = 1; r <= row; ++r) {
      for (int c = 1; c <= col; ++c) {
        sums[r][c] = sums[r - 1][c] + sums[r][c - 1] - sums[r - 1][c - 1] + matrix[r - 1][c - 1];
      }
    }
  }

  public int sumRegion(int row1, int col1, int row2, int col2) {
    return sums[row2 + 1][col2 + 1] - sums[row2 + 1][col1] - sums[row1][col2 + 1] + sums[row1][col1];
  }
}

// Your NumMatrix object will be instantiated and called as such:
// NumMatrix numMatrix = new NumMatrix(matrix);
// numMatrix.sumRegion(0, 1, 2, 3);
// numMatrix.sumRegion(1, 2, 3, 4);

 

307. 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.
 

Both update and getSum is O(logn).

Fenwick Tree(Binary Indexed Tree) References:

http://www.geeksforgeeks.org/binary-indexed-tree-or-fenwick-tree-2/

https://en.wikipedia.org/wiki/Fenwick_tree

https://www.youtube.com/watch?v=CWDQJGaN1gY

 Segment Tree References:

https://en.wikipedia.org/wiki/Segment_tree

https://www.youtube.com/watch?annotation_id=32b44f2a-e16f-4fb3-821d-cf0834915b9c&feature=cards&src_vid=CWDQJGaN1gY&v=ZBHKZF5w4YU

 

Fenwick Tree Solution (which is faster than the segment tree solution.)

public class NumArray {
  private int[] tree;
  private int[] nums;

  public NumArray(int[] nums) {
    this.tree = new int[nums.length + 1];  //First node for Fenwick Tree is a dummy node.
    this.nums = nums;
    for (int i = 0; i < nums.length; ++i) {
      updateTree(i, nums[i]);
    }
  }

  private void updateTree(int i, int deltaDiff) {
    i += 1;
    while (i <= nums.length) {
      tree[i] += deltaDiff;
      i += i & (-i); // get the last bit, and add to itself to update its next pointer.
    }
  }

  public void update(int i, int val) {
    updateTree(i, val - nums[i]);
    nums[i] = val;
  }

  private int getSum(int i) {
    i += 1;
    int sum = 0;
    while (i > 0) {
      sum += tree[i];
      i -= i & (-i);// get the last bit, and subtract to itself to get its parent.
    }
    return sum;
  }

  public int sumRange(int i, int j) {
    if (i == 0) return getSum(j);
    return getSum(j) - getSum(i - 1);
  }
}


// Your NumArray object will be instantiated and called as such:
// NumArray numArray = new NumArray(nums);
// numArray.sumRange(0, 1);
// numArray.update(1, 10);
// numArray.sumRange(1, 2);

 

Segment Tree Solution (which is slower than the Fenwick tree solution):

public class NumArray {

  private class TreeNode {
    private int start;
    private int end;
    int val = 0;
    TreeNode left = null;
    TreeNode right = null;

    public TreeNode(int start, int end) {
      this.start = start;
      this.end = end;
    }
  }

  private TreeNode root = null;
  private int[] nums = null;

  //[start, end]
  // alternatively, you can build the tree using an array, like doing heap sort.
  // check this youtube:
  // https://www.youtube.com/watch?annotation_id=32b44f2a-e16f-4fb3-821d-cf0834915b9c&feature=cards&src_vid=CWDQJGaN1gY&v=ZBHKZF5w4YU
  private TreeNode build(int start, int end) {
    TreeNode node = new TreeNode(start, end);
    if (start == end) {
      node.val = nums[start];
      return node;
    }

    int mid = start + (end - start) / 2;
    node.left = build(start, mid);
    node.right = build(mid + 1, end);
    node.val = node.left.val + node.right.val;
    return node;
  }

  private void update(TreeNode node, int i, int update) {
    if (node == null)
      return;
    if (node.start == node.end) {  // at leaf nodes.
      node.val = update; //update leaf node.
      return;
    }

    int mid = node.start + (node.end - node.start) / 2;
    if (i <= mid)
      update(node.left, i, update); // at left branch
    else
      update(node.right, i, update); // at right branch

    node.val = node.left.val + node.right.val;  //update current node
  }

  //[start, end]
  private int getSum(TreeNode node, int start, int end) {
    start = Math.max(start, node.start);
    end = Math.min(end, node.end);

    if (start == node.start && end == node.end)
      return node.val;

    int mid = node.start + (node.end - node.start) / 2;
    if (start > mid)
      return getSum(node.right, start, end);
    if (end <= mid)
      return getSum(node.left, start, end);
    return getSum(node.left, start, mid) + getSum(node.right, mid + 1, end);
  }

  public int getSum(int start, int end) {
    return getSum(root, start, end);
  }

  public NumArray(int[] nums) {
    if (nums == null || nums.length == 0)
      return;
    this.nums = nums;
    this.root = build(0, nums.length - 1);
  }

  void update(int i, int val) {
    update(root, i, val);
  }

  public int sumRange(int i, int j) {
    return getSum(i, j);
  }
}

// Your NumArray object will be instantiated and called as such:
// NumArray numArray = new NumArray(nums);
// numArray.sumRange(0, 1);
// numArray.update(1, 10);
// numArray.sumRange(1, 2);

  

308. Range Sum Query 2D - Mutable

http://www.cnblogs.com/yrbbest/p/5058571.html

 

 
 
 
 
 
 
posted @ 2016-07-17 12:34  新一代的天皇巨星  阅读(180)  评论(0)    收藏  举报