给定一个由N个整数组成的数组A [] ,其中每个值代表第i个学生的分数,任务是找到需要分配的最小巧克力数量,使得:
- 每个学生应获得至少一种巧克力
- 分数较高的学生应比相邻的学生获得更多的巧克力。
例子:
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
方法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; i,j向前移动,并根据下一个值(a [j + 1])更新val 。 如果子数组正在减少,则将i指向子数组的起点,并将j向前移动直到下一个过渡点。 val,直到子数组末尾才更新res 。在这种情况下, val保留从先前的子数组获得的峰值元素的值。在递减序列结束时,使用get_sum函数更新res,并更新val以指向下一个人持有的巧克力数量。 五,例子: 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 下面是上述方法的代码 时间复杂度: O(N),N是数组的长度 空间复杂度: O(1)
C
// C program for above approach
#include
C++
// C++ program for above approach
#include
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