Wednesday, September 13th

 Candy Distribution

Given a number of children, and a rating array that values each student, distribute the candy such every student gets at least 1 candy, and a child rated higher than their neighbors receives more candy

HARIBO gummy bears, by Thomas Rosenau via Wikipedia.  Shared under the Creative Commons Attribution-Share Alike 2.5 Generic license.  No changes made.

The idea is to keep an array that stores the number of candies each chid gets.  To populate the array, we make 2 passes over the ratings array, a pass in each direction, left-to-right and right-to-left

First we initialize an array to store the candy distributions.  Since every kid gets at least 1 candy so we initialize to 1

vector<int> candies(n,1);

Then we make a pass of the ratings array left to right.  If a child has a rating higher than the neighbor to the left, set the child's rating to the left neighbor +1

for(int i=1; i<n; i++) {
if(ratings[i-1]<ratings[i]) {
candies[i]=candies[i-1]+1;
}
}

We next make a pass over the array from right to left.  In a simple case when a child has a higher rating than his right neighbor, we set the child to his right neighbors number of candy +1.  But we also must test for peaks.  If the child has a higher rating than both left and right neighbors, then their value is the max of the 2 neighbors, plus 1

for(int i=n-2; i>=0; i--) {
if(ratings[i+1]<ratings[i]) {
if(i>=1 && ratings[i]>ratings[i-1]) {
candies[i]=max(candies[i-1], candies[i+1])+1;
}
else {
candies[i]=candies[i+1]+1;
}
}
}

After 2 passes, the candies array contains the candy distributed to each child.  Iterate through it and sum up the total number of candies to return

 int sum=0;
for(int i=0; i<n; i++) {
sum+=candies[i];
}
return sum;

In my initial implementation, I had a first pass that checked for valleys and initialized just those indices with 1, but came to see that all indices can be initialized to 1 without issue

It's also pretty straightforward to sum up candy distributions without the uses of an extra array.  Omitting the candies array and summing up during the 2 passes can lead to a runtime that beats 99% of submissions, as well as obviously using less space.  The candies array keeps the code easy to follow, though, and was definitely helpful during debugging.

There is another solution that uses slope recognition to compute the number of candies in a single pass

This was listed as a hard problem, but maybe more of a medium.  Full code below

    int candy(vector<int>& ratings) {
int n=ratings.size();
if(n==1) return 1;

vector<int> candies(n,1);
for(int i=1; i<n; i++) {
if(ratings[i-1]<ratings[i]) {
candies[i]=candies[i-1]+1;
}
}
for(int i=n-2; i>=0; i--) {
if(ratings[i+1]<ratings[i]) {
if(i>=1 && ratings[i]>ratings[i-1]) {
candies[i]=max(candies[i-1], candies[i+1])+1;
}
else {
candies[i]=candies[i+1]+1;
}
}
}

int sum=0;
for(int i=0; i<n; i++) {
sum+=candies[i];
}
return sum;
}

Comments

Popular posts from this blog

Wednesday, September 20th

Monday, September 11th

Tuesday, September 19th