【算法】Candy 分发糖果

文章目录

  • Candy 分发糖果
    • 问题描述:
    • 分析
    • 代码

Candy 分发糖果

问题描述:

n 个孩子站成一排。给你一个整数数组 ratings 表示每个孩子的评分。

你需要按照以下要求,给这些孩子分发糖果:

  • 每个孩子至少分配到 1 个糖果。
  • 相邻两个孩子评分更高的孩子会获得更多的糖果。
    请你给每个孩子分发糖果,计算并返回需要准备的 最少糖果数目 。

n 范围[1,20000]

ratings[i] 范围[1,20000]

分析

rating数组表示了每个child的分数,而且数据范围很大。
在这个数据规模下,对数级的算法应该是勉强可以通过的,而ONN的算法是必然TLE的。
如果用c[]表示分的candy数。
要求每个人至少要有1个candy,而且另一个条件是当rating[i]比它相邻的得分大,那么i就应该分的candy是max(c[i-1],c[i+1])+1.
那么当rating[i-1]==rating[i]时,是不受限制的,假如c[i-1]==100,那么c[i]最小可以是1。
所以目标就是确定每个child,可以最少分多少。
数组元素必然是递增,递减,相等这些情况组合的。从左到右遍历,如果rating[i-1]rating[i+1],c[i] =max(c[i], c[i+1]+1),否则c[i]=1,因为此时c已经有值,所以c[]的最小值已经确定,但是在从右向左遍历时,可能会导致c[]受右侧影响,要比之前的要大。
2次遍历之后,c[]就是符合最小的分配candy数。
时间复杂度ON,空间ON

还有一个思路是空间O1,但是比较难想,有机会再补吧。

这个问题其实还可以增加点难度,如果数组是循环的,是一个环,如何处理。

代码

public int candy(int[] ratings) {
        int n = ratings.length;
        int[] c = new int[n];
        for (int i = 0; i < n; i++) {
            if (i > 0 && ratings[i] > ratings[i - 1]) {
                c[i] = c[i - 1] + 1;
            } else {
                c[i] = 1;
            }
        } 
        int ans =0;
        for (int i = n-1; i >=0; i--) {
            if (i+1 <n && ratings[i+1] < ratings[i]) {
                c[i] = Math.max(c[i],c[i+1] + 1) ;
            } else {
                c[i] = Math.max(c[i],1);
            }
            ans += c[i];
        } 
        return ans; 
    }

时间复杂度 O(N)

空间复杂度: O(N)

Tag

Array greedy

你可能感兴趣的:(数据结构与算法,算法)