给定一个由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初始化长度为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以指向下一个人持有的巧克力数量。
五、例子:
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
以下是上述方法的代码
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