📜  巧克力分配问题| 2套

📅  最后修改于: 2021-09-06 06:33:33             🧑  作者: Mango

给定一个由N 个整数组成的数组A[] ,其中每个值代表第i学生的分数,任务是找到需要分发的最小巧克力数量,使得:

  • 每个学生应获得至少一块巧克力
  • 分数较高的学生应该比相邻的学生获得更多的巧克力。

例子:

方法一:

方法:该问题可以使用贪心方法解决。请按照以下步骤解决问题:

  • 1初始化长度为N 的数组B[]
  • 从左到右从i = 1 到 N – 1遍历,如果A[i]大于A[i-1] ,则将B[i]更新为B[i] = B[i-1]+1
  • 完成上述步骤后,再次从右到左从i = N – 2 到 0 ,更新B[i]B[i] = max(B[i], B[i+1]+1) if A [i]大于A[i + 1] 。否则,将B[i]更新为B[i] = max(B[i], 1)
  • 遍历后,计算数组B[]的总和并将其打印为所需的最小糖果数。

下面是上述方法的实现:

C++
// C++ program for the above approach
 
#include 
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


C
// C program for above approach
#include 
 
// 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 
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


输出:
12

时间复杂度: O(N),其中 N 是给定数组的长度。
辅助空间: O(N)

方法二:高效方法

仔细观察,空间复杂度可以降低到O(1)。

一、观察:

  • 标记数组将是严格递增、严格递减或平坦(值与两个邻居相同)子数组的组合。
  • 为了尽量减少分发的巧克力总数,一个人和至少一个邻居收到的巧克力数量应该**相差 1 或更少。

** 下面提到了第二次观察的例外情况

二、分发巧克力

情况一:子数组严格递增

如果值严格增加,则给予i th的巧克力数量 学生将比给第(i-1)学生的巧克力数量多(对于任何 i > 0)

一个巧克力将给子阵列中最左边的人,第二个给两个,依此类推,直到得分最高的人。

对于长度为 k 的严格递增子数组,巧克力分布将为 [1, 2, … , k]。

情况 2:子数组严格递减

i学生的巧克力数量将比给第(i+1)学生的巧克力多1(对于任何 i < n-1),最右边的人有一颗巧克力,最左边的人有最大数量的巧克力.

对于长度为 k 的严格递减子数组,巧克力分布将为 [k, k-1, … ,1]。

案例 3:扁平序列

鉴于得分最高的学生将获得比邻居更多的巧克力。因此,如果值相等,则没有依赖性。将分配最小值以获得最佳结果。

一个巧克力将在位置给予人如果两个相邻的值等于A [1]即,[I-1] == A [1] == A [1 + 1]

对于长度为 k 的平面子阵列,巧克力分布将为 [1, 1, … ,1]。

**分配值与相邻元素的差值可能大于 1,如果平面序列中有一个元素并且它正好位于递增和递减序列之间

过渡点:子阵列的趋势(增加/减少/平坦性)发生变化的点。

  • 峰值点:一个递增序列的终点和另一个递减序列的起点

那么分配的值将是max(k1, k2)

其中 k1 – 从递增序列中获得的值,

k2 – 从递减序列中获得的值。

该点将仅被视为递增或递减序列的一部分

三、结果 :

 由于递增/递减序列中的值相差 1,因此在 k 个元素的特定子数组中分配给学生的巧克力数量将是 k 个自然数的总和。由于所有值都是 1,因此对于平面序列,计数将为 k。所需的值将是子数组结果的总和。

四、执行:

考虑变量i, j最初指向第一个元素,val = 1,res = 0。

遍历数组res 后给出分发的巧克力总数。

val迭代索引j (在递增/平坦子数组中)表示人在j处收到的巧克力数量

如果子数组是递增的或者是一个扁平的序列,则将val加到res; i, j向前移动, val根据下一个值 (a[j + 1]) 更新。

如果子数组在递减,则i指向子数组的起点, j向前移动直到下一个过渡点。 val, res直到子数组结束才更新。在这种情况下val保存从前一个子数组获得的峰值元素的值。在递减序列的末尾,使用 get_sum函数更新res并更新val以指向下一个人持有的巧克力数量。

五、例子:

以下是上述方法的代码

C

// C program for above approach
#include 
 
// 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 
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

蟒蛇3

# 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
输出
Minimum number of chocolates = 16

时间复杂度: O(N),N 是数组的长度

空间复杂度: O(1)

如果您想与行业专家一起参加直播课程,请参阅Geeks Classes Live