Skip to content
Related Articles

Related Articles

Improve Article

Chocolate Distribution Problem | Set 2

  • Difficulty Level : Hard
  • Last Updated : 26 Aug, 2021

Given an array A[] consisting of N integers, where each value represents the marks of the ith student, the task is to find the minimum number of chocolates required to be distributed such that:

  • Each student should be awarded with at least one chocolate
  • A student with higher marks should be awarded more chocolates than his adjacent students.

Examples:

Input: A[] = {10, 30, 20}
Output: 4
Explanation : Since, 30 is larger than its adjacent, so the second student must get more chocolates. Therefore, the minimum chocolates can be distributed as {1, 2, 1} = 1 + 2 + 1 = 4

Input: A[] = {23, 14, 15, 14, 56, 29, 14}
Output: 12
 

Method 1:



Approach: The problem can be solved using Greedy approach. Follow the steps below to solve the problem:

  • Initialize array B[] of length N with 1.
  • Traverse from left to right from i = 1 to N – 1, updating B[i] as B[i] = B[i-1]+1 if A[i] greater the A[i-1].
  • After completing the above step, traverse again from right to left from i = N – 2 to 0, updating B[i] as B[i] = max(B[i], B[i+1]+1) if A[i] is greater than A[i + 1]. Otherwise, update B[i] as B[i] = max(B[i], 1).
  • After traversing, calculate the sum of the array B[] and print it as the minimum number of candies required.

Below is the implementation of the above approach:

C++




// C++ program for the above approach
  
#include <iostream>
using namespace std;
  
// FUnction to print minimum number
// of candies required
void minChocolates(int A[], int N)
{
    int B[N];
  
    // Distribute 1 chocolate to each
    for (int i = 0; i < N; i++) {
        B[i] = 1;
    }
  
    // Traverse from left to right
    for (int i = 1; i < N; i++) {
        if (A[i] > A[i - 1])
            B[i] = B[i - 1] + 1;
        else
            B[i] = 1;
    }
  
    // Traverse from right to left
    for (int i = N - 2; i >= 0; i--) {
        if (A[i] > A[i + 1])
            B[i] = max(B[i + 1] + 1, B[i]);
        else
            B[i] = max(B[i], 1);
    }
  
    // Initialize sum
    int sum = 0;
  
    // Find total sum
    for (int i = 0; i < N; i++) {
        sum += B[i];
    }
  
    // Return sum
    cout << sum << "\n";
}
  
// Driver Code
int main()
{
  
    // Given array
    int A[] = { 23, 14, 15, 14, 56, 29, 14 };
  
    // Size of the given array
    int N = sizeof(A) / sizeof(A[0]);
  
    minChocolates(A, N);
}

Java




// Java program for the above approach
import java.util.*;
class GFG {
  
    // FUnction to print minimum number
    // of candies required
    static void minChocolates(int A[], int N)
    {
        int[] B = new int[N];
  
        // Distribute 1 chocolate to each
        for (int i = 0; i < N; i++) {
            B[i] = 1;
        }
  
        // Traverse from left to right
        for (int i = 1; i < N; i++) {
            if (A[i] > A[i - 1])
                B[i] = B[i - 1] + 1;
            else
                B[i] = 1;
        }
  
        // Traverse from right to left
        for (int i = N - 2; i >= 0; i--) {
            if (A[i] > A[i + 1])
                B[i] = Math.max(B[i + 1] + 1, B[i]);
            else
                B[i] = Math.max(B[i], 1);
        }
  
        // Initialize sum
        int sum = 0;
  
        // Find total sum
        for (int i = 0; i < N; i++) {
            sum += B[i];
        }
  
        // Return sum
        System.out.print(sum + "\n");
    }
  
    // Driver Code
    public static void main(String[] args)
    {
  
        // Given array
        int A[] = { 23, 14, 15, 14, 56, 29, 14 };
  
        // Size of the given array
        int N = A.length;
        minChocolates(A, N);
    }
}
  
// This code contributed by shikhasingrajput

Python3




# Python3 program for the above approach
  
# Function to print minimum number
# of candies required
  
  
def minChocolates(A, N):
  
    B = [1 for i in range(N)]
  
    # Traverse from left to right
    for i in range(1, N):
        if (A[i] > A[i - 1]):
            B[i] = B[i - 1] + 1
        else:
            B[i] = 1
  
    # Traverse from right to left
    for i in range(N - 2, -1, -1):
        if (A[i] > A[i + 1]):
            B[i] = max(B[i + 1] + 1, B[i])
        else:
            B[i] = max(B[i], 1)
  
    # Initialize sum
    sum = 0
  
    # Find total sum
    for i in range(N):
        sum += B[i]
  
    # Return sum
    print(sum)
  
  
# Driver Code
if __name__ == '__main__':
  
    # Given array
    A = [23, 14, 15, 14,
         56, 29, 14]
  
    # Size of the given array
    N = len(A)
  
    minChocolates(A, N)
  
# This code is contributed by mohit kumar 29

C#




// C# program for the above approach
using System;
public class GFG {
  
    // FUnction to print minimum number
    // of candies required
    static void minChocolates(int[] A, int N)
    {
        int[] B = new int[N];
  
        // Distribute 1 chocolate to each
        for (int i = 0; i < N; i++) {
            B[i] = 1;
        }
  
        // Traverse from left to right
        for (int i = 1; i < N; i++) {
            if (A[i] > A[i - 1])
                B[i] = B[i - 1] + 1;
            else
                B[i] = 1;
        }
  
        // Traverse from right to left
        for (int i = N - 2; i >= 0; i--) {
            if (A[i] > A[i + 1])
                B[i] = Math.Max(B[i + 1] + 1, B[i]);
            else
                B[i] = Math.Max(B[i], 1);
        }
  
        // Initialize sum
        int sum = 0;
  
        // Find total sum
        for (int i = 0; i < N; i++) {
            sum += B[i];
        }
  
        // Return sum
        Console.Write(sum + "\n");
    }
  
    // Driver Code
    public static void Main(String[] args)
    {
  
        // Given array
        int[] A = { 23, 14, 15, 14, 56, 29, 14 };
  
        // Size of the given array
        int N = A.Length;
        minChocolates(A, N);
    }
}
  
// This code is contributed by 29AjayKumar

Javascript




<script>
  
// javascript program for the above approach
  
    // FUnction to prlet minimum number
    // of candies required
    function minChocolates(A, N)
    {
        let B = new Array(N).fill(0);
  
        // Distribute 1 chocolate to each
        for (let i = 0; i < N; i++) {
            B[i] = 1;
        }
  
        // Traverse from left to right
        for (let i = 1; i < N; i++) {
            if (A[i] > A[i - 1])
                B[i] = B[i - 1] + 1;
            else
                B[i] = 1;
        }
  
        // Traverse from right to left
        for (let i = N - 2; i >= 0; i--) {
            if (A[i] > A[i + 1])
                B[i] = Math.max(B[i + 1] + 1, B[i]);
            else
                B[i] = Math.max(B[i], 1);
        }
  
        // Initialize sum
        let sum = 0;
  
        // Find total sum
        for (let i = 0; i < N; i++) {
            sum += B[i];
        }
  
        // Return sum
        document.write(sum + "<br/>");
    }
  
// Driver Code
      
    // Given array
        let A = [ 23, 14, 15, 14, 56, 29, 14 ];
  
        // Size of the given array
        let N = A.length;
        minChocolates(A, N);
  
</script>
Output: 
12

 

Time Complexity: O(N) where N is the length of the given array.
Auxiliary Space: O(N)

Method 2 : Efficient approach

On careful observation, the space complexity can be reduced to O(1).

I. Observation:

  • Marks array will be a combination of strictly increasing, strictly decreasing or flat (value is same as both the neighbors) subarrays.
  • To minimize the total number of chocolates distributed, the number of chocolates received by a person and at least one of the neighbors should **differ by 1 or less.

** An exception of second observation is mentioned below

II. Distributing chocolates



Case 1: subarray is strictly increasing

If the values are strictly increasing, number of chocolates given to ith student will be one more than the number of chocolates given to (i-1)th  student (for any i > 0)

One chocolate will be given to the left most person in subarray, two the next and so on incrementally up to the person with highest marks.

For a strictly increasing subarray of length k, the chocolate distribution will be [1, 2, … , k].

Case 2 : subarray is strictly decreasing

Number of chocolates given to ith student will be one more than the chocolates given to (i+1)th  student ( for any i < n-1) with one chocolate to the rightmost person and max number to the leftmost person of the subarray.

For a strictly decreasing subarray of length k, the chocolate distribution will be [k, k-1, … ,1].

Case 3 : flat sequence

Given that a student with highest marks will be awarded more number of chocolates than neighbors. So there is no dependency if the values are equal. Minimum value will be assigned for optimal result.

One chocolate will be given to person at position i if both the adjacent values are equal to a[i] i.e, a[i-1] == a[i] == a[i+1]

For a flat subarray of length k, the chocolate distribution will be [1, 1, … ,1].

**The difference for an assigned value with both the neighbors may be greater than 1, if there is a single element in flat sequence and it lies exactly between an increasing & decreasing sequence

Transition points: The points where the trend(increasing/ decreasing/ flat nature) of subarray changes.



  • Peak point : Point which is end point of one increasing sequence and start point of other decreasing sequence

then value assigned will be max(k1, k2)

where k1 – value obtained from increasing sequence,

k2 – value obtained from decreasing sequence.

This point will be considered as part of either increasing or decreasing sequence only 

III. Result : 

 As the values in an increasing/decreasing sequence differ by 1, the number of chocolates distributed to students in a specific subarray of k elements will be  sum of k natural numbers. And the count will be k for a flat sequence as all the values are 1. The required value will be the total sum of the results of subarrays.

IV. Implementation:

Consider variables i, j initially pointing to first element, val = 1, res = 0.

After traversing through the array res gives the total number of chocolates distributed.

val while iterating index j (in increasing/flat subarray) represents the number of chocolates received by the person at j

If the subarray is increasing or a flat sequence, val is added to res; i, j are moved forward and val is updated according to next value (a[j + 1]).

If the subarray is decreasing, i is pointed to the starting point of subarray and j is moved forward till next transition point. val, res are not updated till the end of the subarray. In this case val holds the value of the peak element obtained from previous subarray. At the end of the decreasing sequence res is updated using get_sum function & val is updated to point to the number of chocolates held by the next person.

V. Example:

Input: A[ ] = {1, 2, 10, 7, 6, 4, 5, 5, 5, 6}

Output : 19

Explanation:

subarray — sequence type    —  count of chocolates

A[0-1] — increasing sequence — [1, 2]

A[2-5] — decreasing sequence — [4, 3, 2, 1]

A[5-6] — increasing sequence — [1, 2]

A[7-7] — flat sequence       — [1]

A[8-9] — increasing sequence — [1, 2]

A[2], A[9] are peak points

Chocolates distribution will be 

[1, 2, 4, 3, 2, 1, 2, 1, 1, 2]

Sum of all values = 19

Below is the code for above approach

C




// C program for above approach
#include <stdio.h>
  
// Helper function to get sum of decreasing sequence
int get_sum(int peak, int start, int end)
{
    /* peak is the value obtained at peak point
       from previous flat/increasing sequence */
  
    /* value obtained from decreasing sequence
     also the count of values in the sequence*/
    int count = end - start + 1;
  
    /* assigning max of values obtained from
     increasing and decreasing sequences */
    peak = (peak > count) ? peak : count;
  
    /* sum of count - 1 values & peak value
     sum of natural numbers : (n * (n + 1))/2 */
    int s = peak + (((count - 1) * count) >> 1);
  
    return s;
}
  
// Function to return minimum number of chocolates
int minChocolates(int a[], int n)
{
    int i = 0, j = 0;
    int res = 0, val = 1;
  
    while (j < n - 1) {
  
        if (a[j] > a[j + 1]) {
            // decreasing sequence
            j += 1;
            continue;
        }
  
        if (i == j)
            // add the chocolates received by that person
            res += val;
        else {
            // end point of decreasing sequence
            res += get_sum(val, i, j);
            val = 1; // reset value at that index
        }
  
        if (a[j] < a[j + 1])
            // increasing sequence
            val += 1;
        else
            // flat sequence
            val = 1;
  
        j += 1;
        i = j;
    }
    // add value of chocolates at position n-1
    if (i == j)
        res += val;
    else
        res += get_sum(val, i, j);
  
    return res;
}
  
// Driver code
int main()
{
  
    int a[] = { 5, 5, 4, 3, 2, 1 };
    int n = sizeof(a) / sizeof(a[0]);
    printf("Minimum number of chocolates = %d",
           minChocolates(a, n));
    return 0;
}
  
// This code is contributed by saitejagampala

C++




// C++ program for above approach
  
#include <iostream>
using namespace std;
  
// Helper function to get sum of decreasing sequence
int get_sum(int peak, int start, int end)
{
    /* peak is the value obtained at peak point
       from previous flat/increasing sequence */
  
    /* value obtained from decreasing sequence
     also the count of values in the sequence*/
    int count = end - start + 1;
  
    /* assigning max of values obtained from
     increasing and decreasing sequences */
    peak = max(peak, count);
  
    /* sum of count - 1 values & peak value
     sum of natural numbers : (n * (n + 1))/2 */
    int s = peak + (((count - 1) * count) >> 1);
  
    return s;
}
  
// Function to return minimum number of chocolates
int minChocolates(int a[], int n)
{
    int i = 0, j = 0;
    int res = 0, val = 1;
  
    while (j < n - 1) {
  
        if (a[j] > a[j + 1]) {
            // decreasing sequence
            j += 1;
            continue;
        }
  
        if (i == j)
            // add the chocolates received by that person
            res += val;
        else {
            // end point of decreasing sequence
            res += get_sum(val, i, j);
            val = 1; // reset value at that index
        }
  
        if (a[j] < a[j + 1])
            // increasing sequence
            val += 1;
        else
            // flat sequence
            val = 1;
  
        j += 1;
        i = j;
    }
    // add value of chocolates at position n-1
    if (i == j)
        res += val;
    else
        res += get_sum(val, i, j);
  
    return res;
}
  
// Driver code
int main()
{
  
    int a[] = { 5, 5, 4, 3, 2, 1 };
    int n = sizeof(a) / sizeof(a[0]);
    cout << "Minimum number of chocolates = "
         << minChocolates(a, n) << "\n";
    return 0;
}
  
// This code is contributed by saitejagampala

Java




// Java program for above approach
  
import java.io.*;
  
class GFG {
    public static void main(String[] args)
    {
        int[] a = { 5, 5, 4, 3, 2, 1 };
        int n = a.length;
        System.out.print("Minimum number of chocolates = "
                         + minChocolates(a, n));
    }
  
    // Function to return minimum number of chocolates
    public static int minChocolates(int[] a, int n)
    {
        int i = 0, j = 0;
        int res = 0, val = 1;
  
        while (j < n - 1) {
  
            if (a[j] > a[j + 1]) {
                // decreasing sequence
                j += 1;
                continue;
            }
  
            if (i == j)
                // add the chocolates received by that
                // person
                res += val;
            else {
                // end point of decreasing sequence
                res += get_sum(val, i, j);
                val = 1; // reset value at that index
            }
  
            if (a[j] < a[j + 1])
                // increasing sequence
                val += 1;
            else
                // flat sequence
                val = 1;
  
            j += 1;
            i = j;
        }
  
        // add value of chocolates at position n-1
        if (i == j)
            res += val;
        else
            res += get_sum(val, i, j);
  
        return res;
    }
  
    // helper function to get sum of decreasing sequence
    public static int get_sum(int peak, int start, int end)
    {
        /* peak is the value obtained at peak point
           from previous flat/increasing sequence */
  
        /* value obtained from decreasing sequence
         also the count of values in the sequence*/
        int count = end - start + 1;
  
        /* assigning max of values obtained from
         increasing and decreasing sequences */
        peak = (peak > count) ? peak : count;
  
        /* sum of count - 1 values & peak value
         sum of natural numbers : (n * (n + 1))/2 */
        int s = peak + (((count - 1) * count) >> 1);
  
        return s;
    }
}
  
// This code is contributed by saitejagampala

Python3




# Python3 program for above approach
  
# Function to return minimum number of chocolates
  
  
def minChocolates(a, n):
    i, j = 0, 0
    val, res = 1, 0
  
    while(j < n - 1):
  
        if(a[j] > a[j + 1]):
            # decreasing sequence
            j += 1
            continue
  
        if(i == j):
            # add the chocolates received by that person
            res += val
        else:
            # end point of decreasing sequence
            res += get_sum(val, i, j)
            val = 1  # reset value at that index
  
        if(a[j] < a[j + 1]):
            # increasing sequence
            val += 1
        else:
            # flat sequence
            val = 1
  
        j += 1
        i = j
  
    # add value of chocolates at position n-1
    if(i == j):
        res += val
    else:
        res += get_sum(val, i, j)
  
    return res
  
  
# Helper function to get sum of decreasing sequence
def get_sum(peak, start, end):
    # peak is the value obtained at peak point
    # from previous flat/increasing sequence
  
    # value obtained from decreasing sequence
    # also the count of values in the sequence
    count = end - start + 1
  
    # assigning max of values obtained from increasing
    # and decreasing sequences
    peak = max(peak, count)
  
    # sum of count - 1 values & peak value
    # sum of natural numbers : (n * (n + 1))/2
    s = peak + (((count-1) * count) >> 1)
  
    return s
  
  
# Driver code
if __name__ == '__main__':
    a = [5, 5, 4, 3, 2, 1]
    n = len(a)
    print('Minimum number of chocolates =', minChocolates(a, n))
  
 # This code is contributed by saitejagampala

Javascript




<script>
// Javascript program for above approach
  
// Function to return minimum number of chocolates
function minChocolates(a,n)
{
    let i = 0, j = 0;
        let res = 0, val = 1;
   
        while (j < n - 1) 
        
            if (a[j] > a[j + 1])
            {
              
                // decreasing sequence
                j += 1;
                continue;
            }
   
            if (i == j)
              
                // add the chocolates received by that
                // person
                res += val;
            else 
            {
              
                // end point of decreasing sequence
                res += get_sum(val, i, j);
                val = 1; // reset value at that index
            }
   
            if (a[j] < a[j + 1])
                // increasing sequence
                val += 1;
            else
                // flat sequence
                val = 1;
   
            j += 1;
            i = j;
        }
   
        // add value of chocolates at position n-1
        if (i == j)
            res += val;
        else
            res += get_sum(val, i, j);
   
        return res;
}
  
// helper function to get sum of decreasing sequence
function get_sum(peak,start,end)
{
    /* peak is the value obtained at peak point
           from previous flat/increasing sequence */
   
        /* value obtained from decreasing sequence
         also the count of values in the sequence*/
        let count = end - start + 1;
   
        /* assigning max of values obtained from
         increasing and decreasing sequences */
        peak = (peak > count) ? peak : count;
   
        /* sum of count - 1 values & peak value
         sum of natural numbers : (n * (n + 1))/2 */
        let s = peak + (((count - 1) * count) >> 1);
   
        return s;
}
  
let a = [5, 5, 4, 3, 2, 1];
let n = a.length;
document.write("Minimum number of chocolates = "
                         + minChocolates(a, n));
  
// This code is contributed by unknown2108
</script>

C#




// C# program for above approach
  
using System;
  
public class GFG{
      
    // Function to return minimum number of chocolates
    public static int minChocolates(int[] a, int n)
    {
        int i = 0, j = 0;
        int res = 0, val = 1;
   
        while (j < n - 1) {
   
            if (a[j] > a[j + 1]) {
                // decreasing sequence
                j += 1;
                continue;
            }
   
            if (i == j)
                // add the chocolates received by that
                // person
                res += val;
            else {
                // end point of decreasing sequence
                res += get_sum(val, i, j);
                val = 1; // reset value at that index
            }
   
            if (a[j] < a[j + 1])
                // increasing sequence
                val += 1;
            else
                // flat sequence
                val = 1;
   
            j += 1;
            i = j;
        }
   
        // add value of chocolates at position n-1
        if (i == j)
            res += val;
        else
            res += get_sum(val, i, j);
   
        return res;
    }
   
    // helper function to get sum of decreasing sequence
    public static int get_sum(int peak, int start, int end)
    {
        /* peak is the value obtained at peak point
           from previous flat/increasing sequence */
   
        /* value obtained from decreasing sequence
         also the count of values in the sequence*/
        int count = end - start + 1;
   
        /* assigning max of values obtained from
         increasing and decreasing sequences */
        peak = (peak > count) ? peak : count;
   
        /* sum of count - 1 values & peak value
         sum of natural numbers : (n * (n + 1))/2 */
        int s = peak + (((count - 1) * count) >> 1);
   
        return s;
    }
      
    static public void Main (){
          
        int[] a = { 5, 5, 4, 3, 2, 1 };
        int n = a.Length;
        Console.WriteLine("Minimum number of chocolates = "
                         + minChocolates(a, n));
          
    }
}
  
// This code is contributed by patel2127
Output
Minimum number of chocolates = 16

Time Complexity : O(N),  N is the length of the array

Space Complexity : O(1)

Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above.

Attention reader! Don’t stop learning now. Get hold of all the important DSA concepts with the DSA Self Paced Course at a student-friendly price and become industry ready.  To complete your preparation from learning a language to DS Algo and many more,  please refer Complete Interview Preparation Course.

In case you wish to attend live classes with experts, please refer DSA Live Classes for Working Professionals and Competitive Programming Live for Students.




My Personal Notes arrow_drop_up
Recommended Articles
Page :