This problem is solvable is time O(NlogN) and constant space O(1), where N is the number of towers.
We have to make m
towers of equal height such that we have to build minimum floors.
Important Observations
1. Because we are building minimum floors,rather than building floors on m
towers and reach equal height, we will try to make m - 1
towers to be of equal height of a target tower.
2. The optimal solution lies in finding such m
towers which have the minimum sum of heights difference.Let the solution be towers having following floors in ascending order:
m1 , m2 , m3 , ....... m floor
The optimal solution has the following property:
The sum of the differences is minimum:
(m - m1) + (m - m2) + (m - m3) + .....(m - (m-1))
Because only then we can say that we need to build minimum number of floors.
So it turns out we need to find set of m floors such that the difference of their heights from the floor with maximum height(within those m towers) is minimum.
Say we have array arr
of length n, depicting the number of floors on each tower.First we sort
the towers by their height.
Then we start finding the sum of the differences
in following way.Say we are at index i
in . We find the following sum:
arr[i + m - 1] - arr[i]
+
arr[i + m - 2] - arr[i]
+
arr[i + m - 3] - arr[i]
+
arr[i + m - 4] - arr[i]
.
.
.
arr[i + 1] - arr[i]
Lets call the sum s1
. Now when we consider the next set of m
towers , meaning towers from indices i + 1
to i + m
, we do not need a loop to compute the sum of differences, it can simply be derived from following:
(m - 1)*arr[i + m] - s1 - ((m-1)*arr[i])
So using this simple mathematical technique, we only need a single for loop for this problem.
The pseudocode for the proposed algorithm is:
Sort the array arr of n towers.
Compute the sum of differences for first set of m towers.
sum = 0
for(i = 1 to m - 1)
{
sum = sum + arr[i] - arr[0]
}
Now for the remaining set of m towers
previous_sum = sum, sum = 0, j = 1
minimum_sum = previous_sum
for(i = m to n - 1)
{
sum = (m-1)*arr[i] - previous_sum - (m - 1)*arr[j - 1]
increment j
if( sum < minimum_sum )
{
minimum_sum = sum
}
previous_sum = sum
}
The answer is minimum_sum.