LeetCode - 303. Range Sum Query - Immutable 简单 dp 或者线段树
题目
解析
dp
一维的动态规划,直接从左到右记录 0~每个位置
的和,然后递归 sums[i] = sums[i-1] + nums[i]
,求出所有的 sums
,然后要求某个区间的和,就直接返回 sums[j] - sums[i-1]
即可,如果 i = 0
,就直接返回 sums[j]
。
public class NumArray {
public int[] sums;
public NumArray(int[] nums) {
if (nums == null || nums.length == 0)
return;
sums = new int[nums.length];
sums[0] = nums[0];
for (int i = 1; i < nums.length; i++) sums[i] = sums[i - 1] + nums[i]; // dp
}
public int sumRange(int i, int j) {
if (i == 0) return sums[j];
return sums[j] - sums[i - 1];
}
}
线段树
public class NumArray {
private interface Merger<E> {
E merge(E a, E b);
}
private class SegmentTree<E> {
private E[] tree;
private E[] data;
private Merger<E> merger;
public SegmentTree(E[] arr, Merger merger) {
this.merger = merger;
data = (E[]) new Object[arr.length];
for (int i = 0; i < arr.length; i++) data[i] = arr[i];
tree = (E[]) new Object[4 * arr.length]; //最多需要 4 * n
buildSegmentTree(0, 0, arr.length - 1);
}
public void buildSegmentTree(int treeIndex, int L, int R) {
if (L == R) {
tree[treeIndex] = data[L];
return;
}
int treeL = treeIndex * 2 + 1;
int treeR = treeIndex * 2 + 2;
int m = L + (R - L) / 2;
buildSegmentTree(treeL, L, m);
buildSegmentTree(treeR, m + 1, R);
tree[treeIndex] = merger.merge(tree[treeL], tree[treeR]);
}
public E query(int qL, int qR) {
if (qL < 0 || qL >= data.length || qR < 0 || qR >= data.length || qL > qR) return null;
return query(0, 0, data.length - 1, qL, qR);
}
private E query(int treeIndex, int L, int R, int qL, int qR) {
if (L == qL && R == qR) {
return tree[treeIndex];
}
int m = L + (R - L) / 2;
int treeL = treeIndex * 2 + 1;
int treeR = treeIndex * 2 + 2;
if (qR <= m) { //和右区间没关系 ,直接去左边查找 [0,4] qR <= 2 [0,2]之间查找
return query(treeL, L, m, qL, qR);
} else if (qL > m) {//和左区间没有关系,直接去右边查找 [0,4] qL > 2 --> [3,4]
return query(treeR, m + 1, R, qL, qR);
} else { //在两边都有,查询的结果 合并
return merger.merge(query(treeL, L, m, qL, m), //注意是查询 [qL,m]
query(treeR, m + 1, R, m + 1, qR)); //查询[m+1,qR]
}
}
}
private SegmentTree<Integer> segTree;
public NumArray(int[] nums) {
if (nums == null || nums.length == 0) return;
Integer[] arr = new Integer[nums.length];
for (int i = 0; i < nums.length; i++) arr[i] = nums[i];
segTree = new SegmentTree<Integer>(arr, new Merger<Integer>() {
@Override
public Integer merge(Integer a, Integer b) {
return a + b;
}
});
}
public int sumRange(int i, int j) {
return segTree.query(i, j);
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论