Can be done in linear time
I just wanted to demonstrate that this problem can be solved in O(N) time. I started with SpiderPig's idea of a RingBuffer. But actually, the buffer doesn't need to wrap around. It can start at the end and grow backwards, meaning it acts like a stack. Also, instead of binary searching the stack to find the insertion point, you can search it linearly.
Although it might seem like a linear search would be slower, it actually makes the worst case time O(N). Each item in the original list is inserted into the stack once. And each item will only need to be searched past once because once it is search past, it will be deleted. So the total of all the searches will only search past each item once.
The worst case for a binary search is if we always need to push to the head of the stack. That case takes O(N log N) time total.
The code
Here is the O(N) time solution. Here is a short explanation:
Buffer
is the sorted stack of possible numbers to be paired. Start
is where the stack starts. If it is at size
, then the stack is empty.
Counts
is an array of how many times we have seen each starting point in buffer
. I needed this because in a list such as:
1 1 1 1 1
there are multiple pairings every time we reach a matching endpoint. This example should have 10 possible pairings. If the question were reworded such that the numbers in between had to be <
instead of <=
, then I wouldn't need the counts
array.
private static long countPairs(List<Integer> list) {
int size = list.size();
int [] buffer = new int[size];
int [] counts = new int[size];
int start = size;
long total = 0;
for (int num : list) {
int i;
boolean found = false;
for (i = start; i < size; i++) {
if (buffer[i] >= num) {
if (buffer[i] == num) {
// Found a match.
total += counts[i]++;
found = true;
start = i;
}
break;
}
}
if (!found) {
// Did not find it, insert it before i.
start = i-1;
buffer[start] = num;
counts[start] = 1;
}
}
return total;
}
findPair(...)
returns a singleint
... but, that int is atotal
, that is computed in a funny way. You need to make your code's description clearer, at the moment it is odd. \$\endgroup\$