- Interval Sum
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.
解法1:Binary Index Tree
/**
* Definition of Interval:
* classs Interval {
* int start, end;
* Interval(int start, int end) {
* this->start = start;
* this->end = end;
* }
* }
*/
class Solution {
public:
/**
* @param A: An integer list
* @param queries: An query list
* @return: The result list
*/
vector<long long> intervalSum(vector<int> &A, vector<Interval> &queries) {
len = A.size();
C.resize(len + 1, 0);
vector<long long> result;
for (int i = 0; i < len; ++i) add(i, A[i]);
int n = queries.size();
for (int i = 0; i < n; ++i) {
result.push_back(sum(queries[i].end) - sum(queries[i].start - 1));
}
return result;
}
private:
vector<long long> C;
int len;
int lowbit(int x) {
return x & (-x);
}
void add(int x, int val) {
x++;
for (int i = x; i <= len; i += lowbit(i)) {
C[i] += val;
}
}
long long sum(int x) {
x++;
long long result = 0;
for (int i = x; i > 0; i -= lowbit(i)) {
result += C[i];
}
return result;
}
};
二刷:
class BinaryIndexTree {
public:
vector<int> C;
int len;
BinaryIndexTree(vector<int> &A) {
len = A.size();
C.resize(len + 1);
for (int i = 0; i < len; ++i) {
add(i, A[i]);
}
}
void add(int index, int val) {
index++;
for (int i = index; i <= len; i += lowbit(i)) {
C[i] += val;
}
}
long long presum(int index) {
index++;
long long result = 0;
for (int i = index; i > 0; i -= lowbit(i)) {
result += C[i];
}
return result;
}
private:
int lowbit(int x) {
return x & (-x);
}
};
class Solution {
public:
/**
* @param A: An integer list
* @param queries: An query list
* @return: The result list
*/
vector<long long> intervalSum(vector<int> &A, vector<Interval> &queries) {
vector<long long> result;
BinaryIndexTree Bit(A);
for (int i = 0; i < queries.size(); ++i) {
result.push_back(Bit.presum(queries[i].end) - Bit.presum(queries[i].start - 1));
}
return result;
}
};
解法2:线段树
/**
* Definition of Interval:
* classs Interval {
* int start, end;
* Interval(int start, int end) {
* this->start = start;
* this->end = end;
* }
* }
*/
class SegmentTree {
public:
SegmentTree * left, * right;
int start, end;
long long sum;
SegmentTree(int start, int end, int sum) : left(NULL), right(NULL), start(start), end(end), sum(sum) {}
static SegmentTree * build(int start, int end, vector<int> & A) {
if (start > end) return NULL;
SegmentTree * root = new SegmentTree(start, end, A[start]);
if (start == end) return root;
int mid = start + (end - start) / 2;
root->left = build(start, mid, A);
root->right = build(mid + 1, end, A);
root->sum = root->left->sum + root->right->sum;
return root;
}
long long query(SegmentTree * root, int start, int end) {
if (start <= root->start && root->end <= end) return root->sum;
if (root->left->end >= end) return query(root->left, start, end);
if (root->right->start <= start) return query(root->right, start, end);
long long leftSum = query(root->left, start, root->left->end);
long long rightSum = query(root->right, root->right->start, end);
return leftSum + rightSum;
}
};
class Solution {
public:
/**
* @param A: An integer list
* @param queries: An query list
* @return: The result list
*/
vector<long long> intervalSum(vector<int> &A, vector<Interval> &queries) {
SegmentTree * root = SegmentTree::build(0, A.size() - 1, A);
vector<long long> result;
int n = queries.size();
for (int i = 0; i < n; ++i) {
result.push_back(root->query(root, queries[i].start, queries[i].end));
}
return result;
}
};
三刷,还是线段树,稍有不同。
/**
* Definition of Interval:
* classs Interval {
* int start, end;
* Interval(int start, int end) {
* this->start = start;
* this->end = end;
* }
* }
*/
class SegmentTree {
public:
SegmentTree *left, *right;
int start, end;
long long sum;
SegmentTree(int _start = 0, int _end = 0, long long _sum = 0) : left(NULL), right(NULL), start(_start), end(_end), sum(_sum) {
}
static SegmentTree * build(vector<int> & A, int start, int end) {
if (start > end) return NULL;
SegmentTree * node = new SegmentTree(start, end, A[start]);
if (start == end) return node;
int mid = start + (end - start) / 2;
node->left = build(A, start, mid);
node->right = build(A, mid + 1, end);
node->sum = node->left->sum + node->right->sum;
return node;
}
static long long query(SegmentTree * root, int start, int end) {
if (start <= root->start && end >= root->end) {
return root->sum;
}
int mid = root->start + (root->end - root->start) / 2;
long long leftSum = 0, rightSum = 0;
if (start <= mid) {
leftSum = query(root->left, start, min(mid, end));
}
if (mid + 1 <= end) {
rightSum = query(root->right, max(mid + 1, start), end);
}
return leftSum + rightSum;
}
};
class Solution {
public:
/**
* @param A: An integer list
* @param queries: An query list
* @return: The result list
*/
vector<long long> intervalSum(vector<int> &A, vector<Interval> &queries) {
SegmentTree * root = SegmentTree::build(A, 0, A.size() - 1);
vector<long long> result;
for (int i = 0; i < queries.size(); ++i) {
result.push_back(SegmentTree::query(root, queries[i].start, queries[i].end));
}
return result;
}
};
解法3: 最简单的presums,对于这题应该是最高效的。
/**
* Definition of Interval:
* classs Interval {
* int start, end;
* Interval(int start, int end) {
* this->start = start;
* this->end = end;
* }
* }
*/
class Solution {
public:
/**
* @param A: An integer list
* @param queries: An query list
* @return: The result list
*/
vector<long long> intervalSum(vector<int> &A, vector<Interval> &queries) {
int n = A.size();
int m = queries.size();
vector<long long> res(m, 0);
vector<long long> presumes(n + 1, 0);
for (int i = 0; i < n; ++i) {
presumes[i + 1] = presumes[i] + A[i];
}
for (int i = 0; i < m; ++i) {
res[i] = presumes[queries[i].end + 1] - presumes[queries[i].start];
}
return res;
}
};