📜  巧克力分销问题|套装2

📅  最后修改于: 2021-04-29 14:06:32             🧑  作者: Mango

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

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

例子:

方法1:

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

  • 1初始化长度N的数组B []
  • i = 1到N – 1从左到右遍历,如果A [i]大于A [i-1],则将B [i]更新为B [i] = B [i-1] +1
  • 完成上述步骤后,从i = N – 2到0再次从右向左遍历如果A为A,则将B [i]更新为B [i] = max(B [i],B [i + 1] +1) [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


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)

方法2:高效的方法

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

一,观察:

  • 标记数组将是严格增加,严格减少或平坦(值与两个邻居相同)子数组的组合。
  • 为了最大程度地减少分发的巧克力总量,一个人和至少一个邻居接收到的巧克力数量应相差1或更小。

**下面提到第二次观察的一个例外

二。分发巧克力

情况1:子数组严格增加

如果该值严格增加,则给i巧克力的数量 学生将一个以上给巧克力的数(i-1)学生(对于任何i> 0)

一种巧克力将被分配给子数组中最左边的人,另一种巧克力被赋予子数组,依此类推,直到得分最高的人。

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

情况2:子数组严格减少

i学生的巧克力数量将比给第(i + 1)学生的巧克力数量(对于任何i

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

情况3:平序

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

如果两个相邻的值都等于a [i],即位置a [i-1] == a [i] == a [i + 1],则在位置i处将给人一个巧克力

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

**如果一个固定元素按固定顺序排列,并且恰好位于递增和递减顺序之间,则与两个邻居分配的值之差可能大于1

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

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

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

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

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

该点仅被视为增加或减少序列的一部分

三,结果 :

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

IV。执行:

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

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

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

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

如果子数组正在减少,则将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

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

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

空间复杂度: O(1)