Range Query, Immutable and Mutable
Range Sum Query - Immutable
Immutable求sum,要想到prifixSum。
public class NumArray {
int[] prefixSum;
public NumArray(int[] nums) {
int n = nums.length;
prefixSum = new int[n + 1];
int sum = 0;
for (int i = 1; i <= n; i++) {
sum += nums[i - 1];
prefixSum[i] = sum;
}
}
public int sumRange(int i, int j) {
return prefixSum[j + 1] - prefixSum[i];
}
}
Range Sum Query 2D - Immutable
public class NumMatrix {
int[][] dp;
public NumMatrix(int[][] matrix) {
if (matrix == null || matrix.length == 0 || matrix[0] == null || matrix[0].length == 0) {
return;
}
int m = matrix.length, n = matrix[0].length;
dp = new int[m + 1][n + 1];
int sum = 0;
for (int i = 1; i <= m; i++) {
sum += matrix[i - 1][0];
dp[i][1] = sum;
}
sum = 0;
for (int j = 1; j <= n; j++) {
sum += matrix[0][j - 1];
dp[1][j] = sum;
}
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= n; j++) {
dp[i][j] = dp[i][j - 1] + dp[i - 1][j] - dp[i - 1][j - 1] + matrix[i - 1][j - 1];
}
}
}
public int sumRegion(int row1, int col1, int row2, int col2) {
if (dp == null) {
return 0;
}
int smallRow = Math.min(row1, row2);
int bigRow = Math.max(row1, row2);
int smallCol = Math.min(col1, col2);
int bigCol = Math.max(col1, col2);
return dp[bigRow + 1][bigCol + 1] - dp[bigRow + 1][smallCol] - dp[smallRow][bigCol + 1] + dp[smallRow][smallCol];
}
}
/**
* Your NumMatrix object will be instantiated and called as such:
* NumMatrix obj = new NumMatrix(matrix);
* int param_1 = obj.sumRegion(row1,col1,row2,col2);
*/
Range Sum Query - Mutable
Mutable且一维时,segment tree是个选择。
public class NumArray {
SegmentTreeNode root;
public NumArray(int[] nums) {
if (nums == null || nums.length == 0) {
return;
}
root = build(nums, 0, nums.length - 1);
}
public void update(int i, int val) {
modify(root, i, val);
}
public int sumRange(int i, int j) {
return query(root, i, j);
}
private int query(SegmentTreeNode root, int start, int end) {
if (start <= root.start && end >= root.end) {
return root.sum;
}
int mid = root.start + (root.end - root.start) / 2;
if (mid >= end) {
return query(root.left, start, end);
} else if (mid + 1 <= start) {
return query(root.right, start, end);
}
int left = query(root.left, start, mid);
int right = query(root.right, mid + 1, end);
return left + right;
}
private SegmentTreeNode modify(SegmentTreeNode root, int i, int val) {
if (root == null || i < root.start || i > root.end) {
return root;
} else if (root.start == i && root.end == i) {
root.sum = val;
return root;
}
SegmentTreeNode left = modify(root.left, i, val);
SegmentTreeNode right = modify(root.right, i, val);
root.sum = left.sum + right.sum;
return root;
}
private SegmentTreeNode build(int[] nums, int start, int end) {
if (start > end) {
return null;
}
SegmentTreeNode root = new SegmentTreeNode(start, end, nums[start]);
if (start < end) {
int mid = start + (end - start) / 2;
root.left = build(nums, start, mid);
root.right = build(nums, mid + 1, end);
root.sum = root.left.sum + root.right.sum;
}
return root;
}
}
class SegmentTreeNode {
int start, end, sum;
SegmentTreeNode left, right;
public SegmentTreeNode(int start, int end, int sum) {
this.start = start;
this.end = end;
this.sum = sum;
}
}
/**
* Your NumArray object will be instantiated and called as such:
* NumArray obj = new NumArray(nums);
* obj.update(i,val);
* int param_2 = obj.sumRange(i,j);
*/