力扣网编程135题:分发糖果(贪心算法)

一. 简介

本文记录力扣网上涉及数组方面的编程题:分发糖果。

这里使用贪心算法的思路来解决(求局部最优,最终求全局最优解):每个孩子只需要考虑与相邻孩子的相对关系。

二. 力扣网编程135题:分发糖果(遍历两遍数组)

n 个孩子站成一排。给你一个整数数组 ratings 表示每个孩子的评分。
你需要按照以下要求,给这些孩子分发糖果:
每个孩子至少分配到 1 个糖果。
相邻两个孩子评分更高的孩子会获得更多的糖果。
请你给每个孩子分发糖果,计算并返回需要准备的 最少糖果数目 。

示例 1:
输入:ratings = [1,0,2]
输出:5
解释:你可以分别给第一个、第二个、第三个孩子分发 2、1、2 颗糖果。

示例 2:
输入:ratings = [1,2,2]
输出:4
解释:你可以分别给第一个、第二个、第三个孩子分发 1、2、1 颗糖果。
第三个孩子只得到 1 颗糖果,这满足题面中的两个条件。

解题思路一:(遍历两遍数组)

我们可以将「相邻的孩子中,评分高的孩子必须获得更多的糖果」这句话拆分为两个规则,分别处理:

左规则:ratings[i-1] < ratings[i],i号孩子的糖果比 i-1号孩子的糖果数量多;

右规则:ratings[i] > ratings[i+1],i号孩子比 i+1号孩子的糖果数量少;

遍历该数组两次,处理出每一个学生分别满足左规则或右规则时,最少需要被分得的糖果数量。每个人最终分得的糖果数量即为这两个数量的最大值。

具体方法如下:
  1. 定义一个数组left[ratingsSize],用于存放满足左规则的糖果数目;变量 right 存放满足右规则的糖果数目;

  2. 满足左规则:从前往后遍历数组,若 ratings[i-1] < ratings[i],则 left[i] = left[i-1] +1,否则,left[i] = 1;

  3. 满足右规则:类似处理,不过是从后往前进行遍历。

若 ratings[i] > ratings[i+1],则 right += 1,否则,right =1。在遍历过程中,求 满足左规则和右规则的糖果数目进行比较,求最大值,同时进行累计。

C语言实现如下:

复制代码
//遍历两次数组,满足条件
//1.左规则:ratings[i-1] < ratings[i], 则ratings[i]=ratings[i-1]+1
//2.右规则:ratings[i] > ratings[i+1],则ratings[i]= ratings[i+1]+1
int candy(int* ratings, int ratingsSize) {
    int i;
    int count = 0;
    int left[ratingsSize];

    //从前往后遍历
    //左规则:ratings[i-1] < ratings[i], 则ratings[i]=ratings[i-1]+1
    for(i = 0; i < ratingsSize; i++) {
        if((i>0) && (ratings[i-1] < ratings[i])) {
            left[i] = left[i-1]+1;
        }
        else {
            left[i] = 1;
        }
    }
    int right = 0;
    //从后往前遍历
    //右规则:ratings[i] > ratings[i+1],则ratings[i]= ratings[i+1]+1
    for(i = ratingsSize-1; i >= 0; i--) {
        if((i < ratingsSize-1) && (ratings[i] > ratings[i+1])) {
            right += 1;
        } 
        else {
            right = 1;
        }
        count += fmax(left[i], right);
    } 
    return count;
}

可以看出,贪心算法的解法的时间复杂度为 O(n),空间负责度为O(n)。

第二种实现如下,也是同样的思路(贪心算法):

复制代码
//贪心算法:
//局部最优:每个孩子只需要关心和她相邻的关系
int candy(int* ratings, int ratingsSize) {
    int i;
    int candies[ratingsSize];
    int right = 0;
    int count = 0;

    memset(candies, 0, ratingsSize*sizeof(int));

    for(i = 0; i < ratingsSize; i++) {
        candies[i] = 1;
    }

    //遵循左规则:从左到右遍历
    //如果 ratings[i-1] < ratings[i]
    for(i = 0; i < ratingsSize; i++) {
        if((i>0) && (ratings[i-1] < ratings[i])) {
            candies[i] = candies[i-1] + 1;
        }
    }

    //遵循右规则:从右向左遍历
    //如果 ratings[i] > ratings[i+1]
    for(i = ratingsSize-1; i>=0; i--) {
        if((i<ratingsSize-1) && (ratings[i] > ratings[i+1])) {
            right += 1;
        }
        else {
            right = 1;
        }
        count += fmax(candies[i], right);
    }

    return count;
}
相关推荐
Matlab程序猿小助手1 分钟前
【MATLAB源码-第303期】基于matlab的蒲公英优化算法(DO)机器人栅格路径规划,输出做短路径图和适应度曲线.
开发语言·算法·matlab·机器人·kmeans
CoderIsArt7 分钟前
CORDIC三角计算技术
人工智能·算法·机器学习
立志成为大牛的小牛7 分钟前
数据结构——二十九、图的广度优先遍历(BFS)(王道408)
数据结构·数据库·学习·程序人生·考研·算法·宽度优先
Alex艾力的IT数字空间10 分钟前
基于PyTorch和CuPy的GPU并行化遗传算法实现
数据结构·人工智能·pytorch·python·深度学习·算法·机器学习
仰泳的熊猫21 分钟前
LeetCode:51. N 皇后
数据结构·c++·算法·leetcode
独自破碎E22 分钟前
LeetCode 381: O(1) 时间插入、删除和获取随机元素 - 允许重复
java·算法·leetcode
Miraitowa_cheems1 小时前
LeetCode算法日记 - Day 81: 最大子数组和
java·数据结构·算法·leetcode·决策树·职场和发展·深度优先
冯诺依曼的锦鲤1 小时前
算法练习:前缀和专题
开发语言·c++·算法
闭着眼睛学算法1 小时前
【双机位A卷】华为OD笔试之【哈希表】双机位A-跳房子I【Py/Java/C++/C/JS/Go六种语言】【欧弟算法】全网注释最详细分类最全的华子OD真题题解
java·c语言·c++·python·算法·华为od·散列表
自信150413057592 小时前
初学者小白复盘15之指针(4)
c语言·数据结构·算法