Candy Distribution Problem in JavaIt is a problem frequently asked in interviews of top IT companies like Google, Amazon, TCS, Accenture, etc. By solving the problem, one wants to check the logical ability, critical thinking, and problem-solving skill of the interviewee. So, in this section, we are going to solve the candy distribution problem with different approaches and logic. Also, we will create Java programs for the same. Problem StatementThe problem states that distribute the minimum number of candies to N children such that:
Note that each child has a rating. The task is to the minimum number of candies you must give. Let's understand the problem through an example. Example 1:Suppose, there are four children A, B, C, and D having 1, 2, 3, and 4 rankings, respectively. Let's distribute the candy one by one to each child. Let's take another example. Example 2: Suppose, there are four children A, B, C, and D having 4, 3, 2, and 1 ranking, respectively. In the first round, we will distribute 1 candy to each child. We observe that child A and child B have the same number of candies while child A has a greater ranking than child B. Therefore, it violates the condition. So, we will distribute 1 more candy to child A. We observe that child A and B satisfies the condition but child B and C does not satisfy the condition. Because B and C are neighbors and have 1-1 candy. Having the same number of candies with different rankings is not allowed. So, we will distribute one more candy to child B. Again, we observe that children A and B have the same number of candies while child A has a greater ranking than child B. So, we will distribute 1 more candy to child A. We observe that children A and B satisfies the condition but child C and D does not satisfy the condition. Because C and D are neighbors and have 1-1 candy. Having the same number of candies with different ranking is not allowed. So, we will distribute one more candy to child C. Again, we observe that children B and C have the same number of candies while child B has a greater ranking than child C. So, we will distribute 1 more candy to child B. We observe that children A and B have the same number of candy while child A has a greater ranking than child B. Therefore, it violates the condition. So, we will distribute 1 more candy to child A. Now, we have distributed the candies according to the conditions specified in the problem. Hence, we require 10 (4 + 3 + 2 + 1) candies to distribute each child. In the above two examples, the ranking of the child was already sorted. So, what if ranking is not in a sorted manner. Special Case Consider the following arrangement of child ranking. 1, 2, 6, 5, 4, 3, 1 Distribute 1-1 candy to each child. We observe that child B has a greater ranking than child A but has the same number of candies which is not fair. So, we will distribute 1 more candy to child B. We observe that child C has a greater ranking than child B but child B has more candy than child C which is not fair. So, we will distribute 1 more candy to child C. We observe that children B and C have the same number of candies while the ranking of the child is C is greater so it is not fair. Distribute 1 more candy to child C. Here, a point to note that children D, E, F, and G have ranks 5, 4, 3, and 1, respectively that are in decreasing order. These arrangements never form a good arrangement. So, in such a case first, distribute candies from left to right and right to left manner. After that, take the max of both the arrays. Left to Right: 1, 2, 3, 1, 1, 1, 1 Right to Left: 1, 1, 5, 4, 3, 2, 1 Max of Both Arrays: 1, 2, 5, 4, 3, 2, 1 Therefore, the final distribution will be 1, 2, 5, 4, 3, 2, 1. Hence, we require minimum 18 (1 + 2 + 5 + 4 + 3 + 2 + 1) candies for distribution. Solution to The ProblemThe problem can be solved by using the following four approaches:
Using Brute Force ApproachIt is the simplest approach for solving the problem. In this approach, we have used a 1D array. An array named candies keeps track over the candies distributed to the children. Initially, we distribute one candy to each child. After that, start tracing the array from left to right fashion. During the tracing of the array, we check the following:
Therefore, the candy distribution for current and previous elements becomes according to the condition specified in the problem statement. In the above step, we have checked the current element with the previous element. Now, we will also check the current element with the next element, in the same step.
Repeat the above conditions for the whole ranking array. If the above tracing does not update the number of candies in the candies[] array, it means that we got a final distribution of candies. At this moment, we should not continue tracing of the array. For tracing the updation of the array, we have used a boolean variable hasChanged that is initially set to true. At last, sum up the elements of the candies[] array. It gives the minimum number of candies required for distribution. Let's implement the above logic in a Java program. DistributeCandy1.java Output: The minimum number of candies require to distribute is: 18 Complexity Analysis For the above approach, the time complexity is O(n2). Because we have traversed the array at most n times and their candy count will be updated once on each traversal. The space complexity for the above approach is O(n) because we have not used any extra space. Using Two ArraysIn this approach, we have used two arrays (left2right and right2left). These two arrays store the number of candies required by the current child taking care of the distribution relative to the left and right neighbors, respectively. For left2right array, we have assumed the following distribution rule: The child with a higher ranking than their left neighbor should always get more candies than their left neighbor. For right2left array, we have assumed the following distribution rule: The child with a higher ranking than their right neighbor should always get more candies than their right neighbor. Initially distribute 1 candy to each child, as we have done in the previous approach. For the same, we have filled the array with 1 by invoking the Arrays.fill() method. After that, start traversing over the arrays. First, we perform traversal over left2right array. If the current element's (i-th) ranking is greater than the it's left neighbor, update the current element's number of candies in the left2right array as left2right[i-1] + 1. Therefore, we see that the number of candies of the current child's is always less than or equal to the number of candies than it's neighbor before updating. Since the current element's (child) candies are always less than or equal candies than its left neighbor before updating. After traversing the left2right array, traverse over the right2left array. If the ranking of the current child (i) is greater than it's right neighbor (i+1), update the current element as right2left[i + 1] + 1. When we have done with both the traversal (left to right and right to left), find the max element combinedly in both arrays. Because it satisfies the left and right neighbor relationship. The array that we get after finding the max(left2right, right2left) is the number of candies each child has. At last, sum up the array to find the minimum number of candies for distribution. The above functionality can also be represented in mathematical function as follows: Where n, represents the length of the ranking array. Let's implement the above logic in a Java program. DistributeCandy2.java Output: The minimum number of candies require to distribute is: 28 Complexity Analysis The time complexity for the above approach is O(n) because we have traversed the array left2right and right2left thrice. The space complexity for the above approach is O(n) because no extra space is used. Using One ArrayThe approach is very similar to the previous one. The only difference is in the number of arrays we have used. Previously, we have used two arrays that make code more complex and require more memory. In order to reduce this problem, we have used a single array named candies[] that keeps tracking of the number of candies to be distributed to the current child. So, in this approach too, we will distribute 1 candy to each child. After that, start traversing over the ranking array from left to right fashion and take care of the distribution relative to the left neighbors only. It means, if the current element's (i-th) ranking is greater than it's left neighbor and has a less or an equal number of candies, update the current child's number of candies in the candies[] array as candies[i-1] + 1. Note: While update array, do not compare the current element (candies[i]) with the previous elements (candies[i-1]) because before updation candies[i] <= candies[i - 1].After that, traverse over the ranking array in right to left fashion. In order to meet the left and right neighbor relation, we need to update the i-th element's candies. In backward traversal, if ranking[i] > ranking[i+1], consider only right neighbor criteria. We need not to update the current element's number of candies as candies[i+1]+1. Update the number of candies of the current element's only if candies[i]<=candies[i+1]. It is because this time we have already updated the candies array during the left to right traversal. Therefore, candies[i] is not necessarily less than or equal to candies[i + 1]. Consequently, if ranking[i] > ranking[i + 1], we can update candies[i] as max(candies[i], candies[i + 1] + 1) that makes candies[i] satisfy both the left neighbor and the right neighbor criteria. When we have done with both the traversal (left to right and right to left), find the max element combinedly of both traversals. Because it satisfies both the left and right neighbor relationship. The array that we get after finding the max(candies[i], candies[i+1]+1) is the number of candies each child has. At last, sum up the candies[] array to find the minimum number of candies for distribution. The above functionality can also be represented in mathematical function as follows: Where n, represents the length of the ranking array. Let's implement the above logic in a Java program. DistributeCandy3.java Output: The minimum number of candies require to distribute is: 21 Complexity Analysis The time complexity for the above approach is O(n) because we have traversed the candies array thrice. The space complexity for the above approach is O(n) because no extra space is used. Single Pass Approach with Constant SpaceThe approach is different form the above three approaches. It depends on the observations. In order to distribute candies according to the problem statement, always distribute candies in terms of increments of 1. The minimum number of candies each child will get is 1. So, in this case, the distribution may take the form like 1, 2, 3, …., n or n, …. , 3, 2, 1. We can add these number of candies that gives the minimum number of candies to distribute. The same can be achieved by using the following mathematical formula: Now, we can see the given ranking that may either in increasing or decreasing order. Whenever the ranking slope will rise, the distribution will take the form 1, 2, 3, …., m. on the other hand, falling slope will take the form k, …. , 3, 2, 1. Here, a challenge arises that the local peak point can be included in only one of the slopes either in rising or falling slope. So, we have to decide in which slope we must include local peak point (n). The peak point should be max of the count determine by the rising and falling slope that satisfies both left and right neighbor criteria. In order to determine the number of candies required for distribution, the peak point should be included in the slope which contains a greater number of points. Let's see the implementation of the approach. In the following Java program, we have used two variables oldSlope and newSlope that is used to determine the occurrence of the peak and valley. For tracing the count of elements on rising and falling slope, we have defined two other variables up and down, respectively. Note that here, we have not included the peak element. Update the total count of candies at the end of a falling slope. If the ranks are in a level of the point, means end of mountains in the graph. While, we reach at the end of the mountain, determine where we have to include peak point. It can be determined by comparing the variables up and down together and up to that point. Thus, the count assigned to the peak element becomes max(up, down) + 1. At this point, reset up and down variables indicating the start of a new mountain. The following figure shows the cases that need to be handled for this example: rankings: [1 2 3 4 5 3 2 1 2 6 5 4 3 3 2 1 1 3 3 3 4 2] Let's implement the above approach in a Java program. DistributeCandy4.java Output: The minimum number of candies require to distribute is: 20 Complexity Analysis The time complexity for the above approach is O(n) because we have traversed ranking array once. The space complexity for the above approach is O(1) because we have used an extra space. |
We provides tutorials and interview questions of all technology like java tutorial, android, java frameworks
G-13, 2nd Floor, Sec-3, Noida, UP, 201301, India