I have a problem, and an OK-ish solution. I'm hoping there's a better solution out there.
The problem
I have an array with around 200,000 integers. Given two indices, i1 and i2, I need to calculate the sum of all elements between i1 and i2. Each integer in the array is between 1 and 4 inclusive. For example:
a = [1, 3, 2, 4, 3, 2, 4, 1];
subsection_sum(a, 0, 3); // returns 6: (1 + 3 + 2)
This operation will be performed around 200,000 times, so needs to be pretty fast. A simple counter in a for loop is O(n), and far too slow. The array is never modified after construction, so it's OK to have a relatively expensive pre-processing stage.
My best solution so far
This algorithm works in O(log n) time:
First pad the original array with zeros until its length is a power of two. Next, split the array into two equal parts and store the sum of each. Then split the array into quarters and store the sum of each. Then eighths. Continue doing this until the array is split into sections 2 elements long. For the 8-element array above, this takes two steps:
halves = [(a[0] + a[1] + a[2] + a[3]), (a[4] + a[5] + a[6] + a[7])]
quarters = [(a[0] + a[1]), (a[2] + a[3]), (a[4] + a[5]), (a[6] + a[7])]
Then given two indices, it is now possible to work out the subsection_sum in O(log n) time. For example, subsection_sum(a, 2, 7) == quarters[1] + halves[1].