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): -3Note:
You may assume that the array does not change.
There are many calls to sumRange function.
Basically, we have an integer array and we want to be able to query the interval sum given two indices (i lower or equal than j), as fast as possible.
O(n^2) Bruteforce Algorithm to Compute Range Sum Query
We can compute the range sum at each query runtime. This bruteforce solution takes O(N^2) quadratic time and is inefficient.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | class NumArray { public: NumArray(vector<int> &nums) { int len = nums.size(); sum = new int*[len]; for (int i = 0; i < len; i ++) { sum[i] = new int[len]; } for (int i = 0; i < len; i ++) { int k = 0; for (int j = i; j < len; j ++) { k += nums[j]; sum[i][j] = k; } } } int sumRange(int i, int j) { return sum[i][j]; } private: int **sum; }; |
class NumArray { public: NumArray(vector<int> &nums) { int len = nums.size(); sum = new int*[len]; for (int i = 0; i < len; i ++) { sum[i] = new int[len]; } for (int i = 0; i < len; i ++) { int k = 0; for (int j = i; j < len; j ++) { k += nums[j]; sum[i][j] = k; } } } int sumRange(int i, int j) { return sum[i][j]; } private: int **sum; };
Using Prefix Sum to Compute Range Query
Base on the following:
1 2 | sum(i, j) = sum(0, j) - sum(0, i - 1); // for i > 0 sum(0, j) are pre-computed. |
sum(i, j) = sum(0, j) - sum(0, i - 1); // for i > 0 sum(0, j) are pre-computed.
We can pre-compute the prefix sum in O(N) time and O(N) space. And we can compute the range sum based on the prefix sum.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | typedef unsigned long long int64; class NumArray { public: NumArray(vector<int> &nums) { int len = nums.size(); sum = new int64[len]; int k = 0; for (int i = 0; i < len; i ++) { k += nums[i]; sum[i] = k; } } int sumRange(int i, int j) { if (i == 0) { return sum[j]; } if (j == 0) { return sum[0]; } return sum[j] - sum[i - 1]; } ~NumArray() { delete [] sum; } private: int64 *sum; }; // Your NumArray object will be instantiated and called as such: // NumArray numArray(nums); // numArray.sumRange(0, 1); // numArray.sumRange(1, 2); |
typedef unsigned long long int64; class NumArray { public: NumArray(vector<int> &nums) { int len = nums.size(); sum = new int64[len]; int k = 0; for (int i = 0; i < len; i ++) { k += nums[i]; sum[i] = k; } } int sumRange(int i, int j) { if (i == 0) { return sum[j]; } if (j == 0) { return sum[0]; } return sum[j] - sum[i - 1]; } ~NumArray() { delete [] sum; } private: int64 *sum; }; // Your NumArray object will be instantiated and called as such: // NumArray numArray(nums); // numArray.sumRange(0, 1); // numArray.sumRange(1, 2);
Range Query via Prefix Sum:
- Teaching Kids Programming – Prefix Sum Algorithm to Compute the Interval Sums
- C++ Range Sum Query – Immutable
- GoLang: Range Sum Query on Immutable Array via Prefix Sum
–EOF (The Ultimate Computing & Technology Blog) —
loading...
Last Post: Case Study: use PHPQuery to Crawl 3000 images from Tumblr
Next Post: Simple Steps Make Website Mobile Friendly (Responsive Design)?
Using 2x less memory. Probably faster too, if tested on non-busy server.
class NumArray {
int* const m_piSums;
public:
NumArray(vector& n) : m_piSums(&n[0]) {
int s = n.size();
for (int i = 1; i < s; i++) {
m_piSums[i] += m_piSums[i-1];
}
}
int sumRange(const int i, const int j) { return m_piSums[j] – (i ? m_piSums[i – 1] : 0); }
};
Thanks, will try that 🙂