Solution
Approach #1 Iterative method [Time Limit Exceeded]
One of the simplest solutions is to consider the sum of every possible subarray with length greater than or equal to and to determine the maximum average from out of those. But, instead of finding out this sum in a naive manner for every subarray with length greater than or equal to separately, we can do as follows.
For every starting point, , considered, we can iterate over the elements of starting from , and keep a track of the found till the current index(). Whenever the index reached is such that the number of elements lying between and is greater than or equal to , we can check if the average of the elements between and is greater than the average found till now or not.
Complexity Analysis
Time complexity : . Two for loops iterating over the whole length of with elements.
Space complexity : . Constant extra space is used.
Approach #2 Using Binary Search [Accepted]
Algorithm
To understand the idea behind this method, let's look at the following points.
Firstly, we know that the value of the average could lie between the range . Here, and refer to the minimum and the maximum values out of the given array. This is because, the average can't be lesser than the minimum value and can't be larger than the maximum value.
But, in this case, we need to find the maximum average of a subarray with atleast elements. The idea in this method is to try to approximate(guess) the solution and to try to find if this solution really exists.
If it exists, we can continue trying to approximate the solution even to a further precise value, but choosing a larger number as the next approximation. But, if the initial guess is wrong, and the initial maximum average value(guessed) isn't possible, we need to try with a smaller number as the next approximate.
Now, instead of doing the guesses randomly, we can make use of Binary Search. With and as the initial numbers to begin with, we can find out the of these two numbers given by . Now, we need to find if a subarray with length greater than or equal to is possible with an average sum greater than this value.
To determine if this is possible in a single scan, let's look at an observation. Suppose, there exist elements, in a subarray within such that their average is greater than . In this case, we can say that
(a_1+a_2+ a_3...+a_j)/j ≥ mid or
(a_1+a_2+ a_3...+a_j) ≥ j*mid or
(a_1-mid) +(a_2-mid)+ (a_3-mid) ...+(a_j-mid) ≥ 0
Thus, we can see that if after subtracting the number from the elements of a subarray with more than elements, within , if the sum of elements of this reduced subarray is greater than 0, we can achieve an average value greater than . Thus, in this case, we need to set the as the new minimum element and continue the process.
Otherwise, if this reduced sum is lesser than 0 for all subarrays with greater than or equal to elements, we can't achieve as the average. Thus, we need to set as the new maximum element and continue the process.
In order to determine if such a subarray exists in a linear manner, we keep on adding to the obtained till the element while traversing over the array. If on traversing the first elements, the becomes greater than or equal to 0, we can directly determine that we can increase the average beyond . Otherwise, we continue making additions to for elements beyond the element, making use of the following idea.
If we know the cumulative sum upto indices and , say and respectively, we can determine the sum of the subarray between these indices(including ) as . In our case, we want this difference between the cumulative sums to be greater than or equal to 0 as discusssed above.
Further, for as the cumulative sum upto the current() index, all we need is sum_j - sum_i ≥ 0 such that j - i ≥ k.
To achive this, instead of checking with all possible values of , we can just consider the minimum cumulative sum upto the index . This is because if the required condition can't be sastisfied with the minimum , it can never be satisfied with a larger value.
To fulfil this, we make use of a variable which again stores the cumulative sums but, its current index(for cumulative sum) lies behind the current index for at an offset of units. Thus, by finding the minimum out of and the last minimum value, we can easily find out the required minimum sum value.
Every time after checking the possiblility with a new value, at the end, we need to settle at some value as the average. But, we can observe that eventually, we'll reach a point, where we'll keep moving near some same value with very small changes. In order to keep our precision in control, we limit this process to precision, by making use of and continuing the process till becomes lesser than 0.00001 .
Complexity Analysis
Let N
be the number of element in the array, and range
be the difference between the maximal and minimal values in the array, i.e. range = max_val - min_val
, and finally the error
be the precision required in the problem.
Time complexity : .
The algorithm consists of a binary search loop in the function of
findMaxAverage()
.At each iteration of the loop, the
check()
function dominates the time complexity, which is of for each invocation.It now boils down to how many iterations the loop would run eventually. To calculate the number of iterations, let us break it down in the following steps.
After the first iteration, the would be , as one can see. Further on, at each iteration, the would be reduced into half. For example, after the second iteration, we would have the as .
As a result, after iterations, the error would become . Given the condition of the loop, i.e. , we can deduct that
To sum up, the time complexity of the algorithm would be .
Space complexity : . Constant Space is used.
Comments
Post a Comment