Amazon Interview Question
SDE1sCountry: United States
Interview Type: In-Person
passing a apple means a child giving away one apple to one of its neighbour.
Even if 2 separate children can pass apples simultaneously that will still be counted as 2 steps and not 1.
If we are allowed to sort the sequence then after sort we can distribute the one apple to its neighbors until everybody has same.
sorting is not allowed as children are sitting in Circle. Moreover when they are lazy enough to share just one apple to their neighbour, then forget about them moving around and arranging themselves in sorted order
// distribute task between smallest and highest
void distribute( size_t CPU[], size_t start, size_t end, bool direction )
{
for( size_t index = start; ; index++ )
{
if( index == end )
{
index = start;
}
if( direction )
{
CPU[index]++;
CPU[index+1]--;
}else
{
CPU[index]--;
CPU[index+1]++;
}
if( 1 >= ::labs( CPU[start] - CPU[end] ) )
{
return;
}
}
}
// there is a circle of N CPU's with amount of tasks loaded on each one.
// Amount of tasks can be devided at N.
// Only one task can be passed between neihgbore CPU's in the circle
void Test17252672()
{
size_t CPU[] = { 2, 9, 3, 6, 5, 1, 2 }; // sum = 28
size_t sumBefore = 0;
for( size_t i = 0; i < _countof(CPU); i++ )
{
sumBefore += CPU[i];
}
CPPUNIT_ASSERT_EQUAL_MESSAGE( "does not pass requeirements", 0, sumBefore % _countof(CPU) );
bool isChanged = true;
size_t minItem = CPU[_countof(CPU) - 1], maxItem = 0;
// neighbor's exchange: share tasks between two CPU's
for( size_t index = 0; isChanged; index++ )
{
size_t next = index + 1;
if( _countof(CPU) - 1 == index )
{
isChanged = false;
next = 0;
}
if( CPU[index] > CPU[next] + 1 )
{
while( 1 < (CPU[index] - CPU[next]) )
{
CPU[ index ]--;
CPU[ next ]++;
}
isChanged = true;
}else
if( CPU[next] > CPU[index] + 1 )
{
while( 1 < (CPU[next] - CPU[index]) )
{
CPU[ next ]--;
CPU[ index ]++;
}
isChanged = true;
}
if( CPU[minItem] >= CPU[ index ] )
{
minItem = index;
}
if( CPU[maxItem] <= CPU[ index ] )
{
maxItem = index;
}
if( _countof(CPU) - 1 == index )
{
index = 0;
}
// adjasment min..max..min or max..min..max and max-min > 1
if( !isChanged && 1 < ( CPU[maxItem] - CPU[minItem] ) )
{
// pass task throw the subchain
distribute( CPU, min(minItem, maxItem), max(minItem, maxItem), minItem < maxItem );
index = 0;
isChanged = true;
}
}
size_t sumAfter = 0;
for( size_t i = 0; i < _countof(CPU); i++ )
{
sumAfter += CPU[i];
}
CPPUNIT_ASSERT_EQUAL_MESSAGE( "does not pass requeirements", 0, sumAfter % _countof(CPU) );
CPPUNIT_ASSERT_EQUAL_MESSAGE( "sums must be the same", sumBefore, sumAfter );
}
// Apple.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <iostream>
using namespace std;
void Pass(int arr[],int i,int N)
{
if(i==0)
{
if(arr[N-1]<N)
{
++arr[N-1];
--arr[i];
}
else
{
if(arr[i+1]<N)
{
++arr[i+1];
--arr[i];
}
else
{
++arr[i+1];
--arr[i];
}
}
}
if(i==(N-1))
{
if(arr[i-1]<N)
{
++arr[i-1];
--arr[i];
}
else
{
if(arr[0]<N)
{
++arr[0];
--arr[i];
}
else
{
++arr[0];
--arr[i];
}
}
}
else
{
if(arr[i-1]<N)
{
++arr[i-1];
--arr[i];
}
else
{
if(arr[i+1]<N)
{
++arr[i+1];
--arr[i];
}
else
{
++arr[i+1];
--arr[i];
}
}
}
}
int _tmain(int argc, _TCHAR* argv[])
{
int N=5;
int arr[5]={3,4,6,10,2};
int count=0;
int flag=1;
while(flag)
{
for(int i=0;i<N;i++)
{
if(arr[i]>N)
{
++count;
Pass(arr,i,N);
}
}
int j;
for(j=0;j<N;j++)
{
if(arr[j]!=N)
{
flag=1;
break;
}
}
if(j==N)
flag=0;
}
std::cout<<"Number of Passes"<<cout;
return 0;
}
This does not and will not work.
what do u mean by N. ...does it stand for children or is it the mean of all the apples children have, i.e. (total apples)/Children ?
use dequeue insert (n/2) element in the queue after that we take element(n/2+1,n/2-1) similarly after that(n/2+2,n/2-2) until complete array in traverse
Condition to add element to the queue is first calculate the number of apples each person must have
n/2-x added from front end and n/2+x added from back end similarly
1 if first apples is greater than average then it remove the elements from queue until all the additional apples is consumed .
2. if apples is less than average then add element to the queue.
complexity = O(n)
Space complexity =O(n)
Its a variant of the problem to find the longest sub-array(circular) that adds up to zero. The array in question, then, would be a sequence of numbers such that, every number = number - (sum of all apples / number of boys).
The maximum number of steps would be = sum of all positive numbers in the subarray found from the modified array.( if you assume that multiple children handing over an apple to their neighbors as a single step).
e.g.: N = 3. and input array is [0,2,7] then modified array is [-3,-1, 4]. So the the guy on the right gave an apple to the guy on the left, guy in the middle gave an apple to guy on left at the same time and so on. so total steps = 4.
In the OP example, where there are
N = 5
Total Apples = 25
Original Array [3, 4, 6, 10, 2]
If # = # - (total/N) wouldn't the Modified Array be [-2, -1, 1, 5, -3]
The sum of the positive values = 6.... in my solution I got 5 steps... am I missing something?
Assumption = (if you assume that multiple children handing over an apple to their neighbors as a single step).
IS NOT ALLOWED
divide the group(circle) into two district and calculate the net flow needed between two districts, and then divide each district into two smaller districts and calculate the net flow between them and also update the net flow between the lager district. Keep doing this till we reach the smallest individual and then we know what should be the flow.
Suppose T is the total number of balls and T/N=X.
Build a graph where each node corresponds to a child which doesn't have X balls.
The edges of the graph are the distances between each pair children (in the shortest direction around the circle) where one child has more than X balls and the other less ten X balls (there are no edges between children that both have more than X balls, or less then X balls).
Now pick the shortest edge, and remove it from the graph. Add to the total cost the distance of the edge multiplied by the number of balls moved, which is the minimum number required to get at least one of the children to X balls (example: first child has X+2 balls, second child X-3 balls, so we move two balls from the first child to the second). Remove the child with X balls from the graph. Repeat for all edges in the graph.
Total time is O(E log E), where E=O(N^2) so it's O(N^2 log N).
def circle_dist(l):
org_len=len(l)
if sum(l)%org_len>0:
return None
avg=sum(l)/org_len
l=[[orgpos,val-avg] for orgpos,val in enumerate(l) if val!=avg]
s=0
while len(l)>0:
#print l
min_dist=None
prev_pos, prev_val = l[-1]
prev_pos-=org_len
for idx in xrange(len(l)):
pos = l[idx][0]
val = l[idx][1]
if val*prev_val<0:
if min_dist==None or pos-prev_pos<min_dist:
min_dist=pos-prev_pos
min_idx=idx
prev_pos=pos
prev_val=val
val=l[min_idx][1]
prev_val=l[min_idx-1][1]
xfr=min(abs(val), abs(prev_val))
s=s+xfr*min_dist
#print min_idx, min_dist, xfr
if val>0:
val-=xfr
else:
val+=xfr
if val==0:
del l[min_idx]
else:
l[min_idx][1]=val
if prev_val>0:
prev_val-=xfr
else:
prev_val+=xfr
if prev_val==0:
del l[min_idx-1]
else:
l[min_idx-1][1]=prev_val
return s
def main():
l=[3,4,6,10,2]
print l
print circle_dist(l)
Explanation of the above solution:
We keep a list of only the children that have extra balls or missing balls. So each item in the list stores the original poisition of the child in the circle, and the number of extra ro missing balls the child has.
In each iteration we find the two closest children (by comparing their original positions) where one has extra balls and the other has missing balls, and then we transfer balls from the child with the extra balls to the child with the missing balls, so that at least one of them has the required number of balls. That child is then removed from the list.
We repeat the above until the list is empty.
Time complexity: O(N^2), space O(N) although the input list can be used for storage required during the computation, so no extra space would be required.
This is incorrect.
Take the example: [1,1,1,1,2,1,0,2,1,0,1,1,1,1]
The minimal steps are 4.
Your result gives 6.
The point is, you cannot just choose the "two closest children".
1.Divide the circle into 2 groups of equal size if even, or one group can be 1 larger if odd.
2.Calculate the diff between 2 groups to make the average apples per child equal
3. do the same for each of the 2 groups until the number of children in the group goes down to one.
4. adds up diffs at different levels between groups, that is the answer: Minimum moves
public class NBoysCircle {
public static void main(String[] args) {
int[] array = {3,4,6,10,2};
int sumOfArray = 3+4+6+10+2;
int distribution = sumOfArray/5;
array = recursiveDivideEqually(array.length, array, distribution);
for(int i =0; i<array.length; i++) {
System.out.println (array[i]+",");
}
}
public static int[] recursiveDivideEqually(int totalCount, int[] array, int distribution) {
boolean arrayModified = false;
for(int i =0; i<totalCount; i++) {
int nextIndex = 0;
int previousIndex = 0;
if(i == totalCount-1) {
nextIndex = 0;
}else {
nextIndex = i+1;
}
if(i == 0) {
previousIndex = totalCount-1;
}else {
previousIndex = i-1;
}
if(array[i] < distribution) {
if(array[nextIndex] > distribution) {
array[i] = array[i] + 1;
array[nextIndex] = array[nextIndex] - 1;
arrayModified = true;
}else if(array[previousIndex] > distribution) {
array[i] = array[i] + 1;
array[previousIndex] = array[previousIndex] - 1;
arrayModified = true;
}else {
array[i] = array[i] + 1;
array[nextIndex] = array[nextIndex] - 1;
arrayModified = true;
}
}else if (array[i] > distribution) {
if(array[nextIndex] < distribution) {
array[i] = array[i] - 1;
array[nextIndex] = array[nextIndex] + 1;
arrayModified = true;
}else if(array[previousIndex] < distribution) {
array[i] = array[i] - 1;
array[previousIndex] = array[previousIndex] + 1;
arrayModified = true;
}
}
}
if(arrayModified) {
recursiveDivideEqually(totalCount, array, distribution);
}
return array;
}
}
Note that for all applicable solutions( not necessarily the minimal one), they share the same property: the net flow for each child is invariant.
So two solutions differ from a flow whose net flow for each child vanishes, that is, a circumfluence like 1->1->...->1.
To find the minimal solution, just start from any initial solution, subtract a circumfluence from it, to minimize the difference between the number of positive edges and negative edges. The constant flow in the circumfluence is the median of the flows in the initial solution.
Take [5,0,0,0,0] as an example, an initial flow is [4,3,2,1,0], with 10 steps. subtract the circumfluence [2,2,2,2,2] from it, we get a flow [2,1,0,-1,-2], with 6 steps. This is the minimal solution since it has equal number of positive edges and negative edges: 2.
The time complexicity is O(n).
It's not clear what does [2,1,0,-1,2] mean ? How does it describe the actual solution ?
Also why did you decide to sunstract [2,2,2,2,2] from the intial solution, and how would your algorithm work for the input of [1,1,1,1,2,1,0,2,1,0,1,1,1,1] ?
[2,1,0,-1,-2] means: boy[0] gives 2 apples to boy[1] and boy[4] each. Then boy[1] gives 1 apple to boy[2]. boy[4] give 1 apple to boy[3].
2 is the median of [4,3,2,1,0]. So we need to subtract [2,2,2,2,2] from that.
for [1,1,1,1,2,1,0,2,1,0,1,1,1,1], the initial flow is:
[0, 0, 0,0,1,1,0,1,1,0,0,0,0,0]
That is: boy[4] gives 1 apple to boy[5], boy[5] passes it to boy[6], and so on.
The median of this array is 0, which means we need to subtract [0,0,....,0] from it, which means we don't need to update this initial solution. It is already optimal.
In the worst case, one boy has all the apples and distributes it around the circle, 1 at a time. So if N is even, in the worst case the number of passes around the circle would be:
Number of passes = N/2 + 2(N/2 - 1) + 2(N/2 - 2)..so on as long as N/2 - 2 > 0
If N is odd:
Number of passes = 2(N/2) + 2(N/2 - 1) + 2(N/2 - 2)..so on as long as N/2 - 2 > 0
"/" is the division operator.
This is the approach I came up with. I'm unsure if it's the optimal solution though. Would love suggestions!
Anyways, the idea is that you evaluate each kid in the circle, if he can pass an apple to someone who needs it behind him, then he does. Otherwise, if they have excess apples, then they just continue to pass it forward.
From the way the question seemed to be phrased, I took it that a pass is a single iteration through all children in the circle, so once everyone has given an apple away (if they can), then the next pass (step) starts.
- Bones April 10, 2013