Given an integer array (index from 0 to n-1, where n is the size of this array), and an query list. Each query has two integers [start, end]
. For each query, calculate the sum number between index start and end in the given array, return the result list.
Example
Example 1:
Input: array = [1,2,7,8,5], queries = [(0,4),(1,2),(2,4)]
Output: [23,9,20]
Example 2:
Input: array : [4,3,1,2], queries : [(1,2),(0,2)]
Output: [4,8]
Challenge
O(logN) time for each query
Notice
We suggest you finish problem Segment Tree Build, Segment Tree Query and Segment Tree Modify first.
思路:因为这个题目不需要modify数组操作,所以用prefix sum array就可以解决,O(N + M) N是数组大小,M是query次数;
注意:prefixsum一般都是用PrefixSum[n+1]的数组,prefix[0] = 0; 那么
因为i, j 是A里面的坐标,而prefixsum比A多了1;所以原来的sum[j] - sum[i-1]变成了
sum(i~j) = prefixsum(j + 1) - prefixsum(i);
/**
* Definition of Interval:
* public classs Interval {
* int start, end;
* Interval(int start, int end) {
* this.start = start;
* this.end = end;
* }
* }
*/
public class Solution {
/**
* @param A: An integer list
* @param queries: An query list
* @return: The result list
*/
public List<Long> intervalSum(int[] A, List<Interval> queries) {
List<Long> list = new ArrayList<>();
int n = A.length;
long[] prefixsum = new long[n + 1];
prefixsum[0] = 0;
for(int i = 1; i <= n; i++) {
prefixsum[i] = prefixsum[i - 1] + A[i - 1];
}
for(Interval interval: queries) {
list.add(prefixsum[interval.end + 1] - prefixsum[interval.start]);
}
return list;
}
}
思路2:其实,这个题目是为了后面的follow up做准备的,LogN time for query;
如果数组是个动态的, 那么就要用到segment tree或者树状数组;
现在这里用segment tree来做解答;Time: m Log(K) , m是query的次数,K是数组里面的最大值;Space: O(N)
/**
* Definition of Interval:
* public classs Interval {
* int start, end;
* Interval(int start, int end) {
* this.start = start;
* this.end = end;
* }
* }
*/
public class Solution {
/**
* @param A: An integer list
* @param queries: An query list
* @return: The result list
*/
public List<Long> intervalSum(int[] A, List<Interval> queries) {
List<Long> list = new ArrayList<>();
SegmentTree segmentTree = new SegmentTree(A);
for(Interval interval: queries) {
list.add(segmentTree.query(interval.start, interval.end));
}
return list;
}
private class SegmentTreeNode {
public int start, end;
public long sum;
public SegmentTreeNode left, right;
public SegmentTreeNode (int start, int end) {
this.start = start;
this.end = end;
this.sum = 0;
this.left = null;
this.right = null;
}
}
private class SegmentTree {
public SegmentTreeNode root;
public int size;
public SegmentTree(int[] A) {
this.size = A.length;
this.root = buildTree(A, 0, size - 1);
}
private SegmentTreeNode buildTree(int[] A, int start, int end) {
if(start > end) {
return null;
}
SegmentTreeNode node = new SegmentTreeNode(start, end);
if(start == end) {
node.sum = A[start];
return node;
}
int mid = start + (end - start) / 2;
node.left = buildTree(A, start, mid);
node.right = buildTree(A, mid + 1, end);
node.sum = node.left.sum + node.right.sum;
return node;
}
private long querySum(SegmentTreeNode root, int start, int end) {
if(root.start == start && root.end == end) {
return root.sum;
}
int mid = root.start + (root.end - root.start) / 2;
long leftsum = 0, rightsum = 0;
if(start <= mid) {
leftsum = querySum(root.left, start, Math.min(mid, end));
}
if(end >= mid + 1) {
rightsum = querySum(root.right, Math.max(start, mid + 1), end);
}
return leftsum + rightsum;
}
public long query(int start, int end) {
return querySum(root, start, end);
}
}
}