Given a vector of n elements of type integer, what is the more efficient algorithm that produce the minimum number of transformation step resulting in a vector that have all its elements equals, knowing that :
Examples :
Given :
0, 3, 0
Then 2 steps are required :
1, 2, 0
1, 1, 1
Given :
3, 0, 3
Then 1 step is required :
2, 2, 2
Given :
4, 0, 0, 0, 4, 0, 0, 0
Then 3 steps are required :
3, 1, 0, 0, 3, 1, 0, 0
2, 1, 1, 0, 2, 1, 1, 0
1, 1, 1; 1, 1, 1, 1, 1
My current algorithm is based on the sums of the integers at each side of an element. But I'm not sure if it produce the minimum steps.
FYI the problem is part of a code contest (created by Criteo http://codeofduty.criteo.com) that is over.
Here is a way. You know the sum of the array, so you know the target number in each cell. Thus you also know the target sum for each subarray. Then iterate through the array and on each step you make a desicion:
Repeat this until no more changes are made (i.e. you only applied 3 for each of the elements).
public static int F(int[] ar)
{
int iter = -1;
bool finished = false;
int total = ar.Sum();
if (ar.Length == 0 || total % ar.Length != 0) return 0; //can't do it
int target = total / ar.Length;
int sum = 0;
while (!finished)
{
iter++;
finished = true;
bool canMoveNext = true;
//first element
if (ar[0] > target)
{
finished = false;
ar[0]--;
ar[1]++;
canMoveNext = ar[1] != 1;
}
sum = ar[0];
for (int i = 1; i < ar.Length; i++)
{
if (!canMoveNext)
{
canMoveNext = true;
sum += ar[i];
continue;
}
if (sum < i * target && ar[i] > 0)
{
finished = false;
ar[i]--;
ar[i - 1]++;
sum++;
}
else if (sum + ar[i] > (i + 1) * target && ar[i] > 0) //this can't happen for the last element so we are safe
{
finished = false;
ar[i]--;
ar[i + 1]++;
canMoveNext = ar[i + 1] != 1;
}
sum += ar[i];
}
}
return iter;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With