From an integer array A[N], I’d like to find an interval [i,j] that has a maximized average (A[i] + A[i + 1] + .. + A[j]) / (j - i + 1).
The length of the interval (j - i + 1) should be more than L.(L >= 1)
What I thought was to calculate an average for every i ~ j, but it is too slow to do like this.(N is too big)
Is there an algorithm faster than O(N^2)? Or I’d like to know whether there exists a randomized method for that.
There is an
O(N*logC)algorithm, whereCis proportional to the maximum element value of the array. Comparing with some more complicated algorithms in recent papers, this algorithm is easier to understand, and can be implemented in a short time, and still fast enough in practical.For simplicity, We assume there is at least one non-negative integers in the array.
The algorithm is based on binary search. At first, we can find that the final answer must be in the range
[0, max(A)], and we half this interval in each iteration, until it is small enough (10-6 for example). In each iteration, assume the available interval is[a,b], we need to check whether the maximum average is no less than(a+b)/2. If so, we get a smaller interval[(a+b)/2, b], or else we get[a, (a+b)/2].Now the problem is: Given a number
K, how to check that the final answer is at leastK?Assume the average is at least
K, there exist somei,jsuch that(A[i] + A[i+1] + ... + A[j]) / (j - i + 1) >= K. We multiply both sides by(j-i+1), and move the right side to left, and we get(A[i] - K) + (A[i+1] - K) + ... + (A[j] - K) >= 0.So, let
B[i] = A[i] - K, we only need to find an interval[i, j](j - i + 1 > L) such thatB[i] + ... + B[j] >= 0. Now the problem is: Given arrayBand lengthL, we are to find an interval of maximum sum whose length is more thanL. If the maximum sum is>= 0, the original average numberKis possible.The second problem can be solved by linear scan. Let
sumB[0] = 0,sumB[i] = B[1] + B[2] + ... + B[i]. For each indexi, the max-sum interval which ended atB[i]issumB[i] - min(sumB[0], sumB[1], ..., sumB[i-L-1]). When scanning the array with increasingi, we can maintain themin(sumB[0], ..., sumB[i-L-1])on the fly.The time complexity of the sub-problem is
O(N). And we needO(logC)iterations, so the total complexity isO(N*logC).P.s. This kinds of “average problem” belongs to a family of problems called fractional programming. The similar problems are minimum average-weighted spanning tree, minimum average-weighted cycle, etc.
P.s. again. The
O(logC)is a loose bound. I think we can reduce it by some careful analysis.