The naive version is not linear. Linear would be O(n). The naive algorithm is O(n*k), where k is the window size. Your improvement also is O(n * k) in the worst case (imagine a sorted array), but in the general case you should see a big improvement in running time because you'll avoid a large number of recalculations.
You can solve this in O(n log k) by using a Min-max heap (or two heaps), but you have to use a type of heap that can remove an arbitrary node in O(log k). You can't use a standard binary heap because although removing an arbitrary node is O(log k), finding the node is O(k).
Assuming you have a Min-max heap, the algorithm looks like this:
heap = create empty heap
add first k items to the heap
for (i = k; i < n-k; ++i)
{
if (heap.MaxItem - heap.MinItem) > threshold
output range
remove item i-k from the heap
add item i to the heap
}
The problem, of course, is removing item i-k from the heap. Actually, the problem is finding it efficiently. The way I've done this in the past is to modify my binary heap so that it stores nodes that contain an index and a value. The heap comparisons use the value, of course. The index is the node's position in the backing array, and is updated by the heap whenever the node is moved. When an item is added to the heap, the Add method returns a reference to the node, which I maintain in an array. Or in your case you can maintain it in a queue.
So the algorithm looks like this:
queue = create empty queue of heap nodes
heap = create empty heap
for (i = 0; i < k; ++i)
{
node = heap.Add(array[i]);
queue.Add(node);
}
for (i = k; i < n-k; ++i)
{
if (heap.MaxItem - heap.MinItem) > threshold
output range
node = queue.Dequeue()
remove item at position node.Index from the heap
node = heap.Add(array[i])
queue.Add(node)
}
This is provably O(n log k). Every item is read and added to the heap. Actually, it's also removed from the heap. In addition, every item is added to the queue and removed from the queue, but those two operations are O(1).
For those of you who doubt me, it is possible to remove an arbitrary element from a heap in O(log k) time, provided that you know where it is. I explained the technique here: https://stackoverflow.com/a/8706363/56778.
So, if you have a window of size 4,000, running time will be roughly proportional to: 3n * 2(log k)
. Given a million items and a window size of 5,000, that works out to 3,000,000 * (12.3 * 2), or about 75 million. That's roughly equivalent to having to recompute the full window in your optimized naive method 200 times.
As I said, your optimized method can end up taking a long time if the array is sorted, or nearly so. The heap algorithm I outlined above doesn't suffer from that.
You should give your "better" algorithm a try and see if it's fast enough. If it is, and you don't expect pathological data, then great. Otherwise take a look at this technique.