【玩转贪心算法专题】135. 分发糖果[困难]

【玩转贪心算法专题】135. 分发糖果[困难]

1、力扣链接

https://leetcode.cn/problems/candy/

2、题目描述

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

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

每个孩子至少分配到 1 个糖果。

相邻两个孩子评分更高的孩子会获得更多的糖果。

请你给每个孩子分发糖果,计算并返回需要准备的 最少糖果数目 。

示例 1:

输入:ratings = [1,0,2]

输出:5

解释:你可以分别给第一个、第二个、第三个孩子分发 2、1、2 颗糖果。

示例 2:

输入:ratings = [1,2,2]

输出:4

解释:你可以分别给第一个、第二个、第三个孩子分发 1、2、1 颗糖果。

第三个孩子只得到 1 颗糖果,这满足题面中的两个条件。

提示:

n == ratings.length

1 <= n <= 2 * 104

0 <= ratings[i] <= 2 * 104

3、题目分析

对于贪心算法的题目,可从 寻求局部最优解入手,以局部最优解,得到全局最优解

本题思路:

分两个阶段

1、起点下标1 从左往右,只要 右边 比 左边 大,右边的糖果=左边 + 1

2、起点下标 ratings.length - 2 从右往左, 只要左边 比 右边 大,此时 左边的糖果应该 取本身的糖果数(符合比它左边大) 和 右边糖果数 + 1 二者的最大值,这样才符合 它比它左边的大,也比它右边大

4、代码实现

1、Java

java 复制代码
class Solution {
    /**
         分两个阶段
         1、起点下标1 从左往右,只要 右边 比 左边 大,右边的糖果=左边 + 1
         2、起点下标 ratings.length - 2 从右往左, 只要左边 比 右边 大,此时 左边的糖果应该 取本身的糖果数(符合比它左边大) 和 右边糖果数 + 1 二者的最大值,这样才符合 它比它左边的大,也比它右边大
    */
    public int candy(int[] ratings) {
        int len = ratings.length;
        int[] candyVec = new int[len];
        candyVec[0] = 1;
        for (int i = 1; i < len; i++) {
            candyVec[i] = (ratings[i] > ratings[i - 1]) ? candyVec[i - 1] + 1 : 1;
        }

        for (int i = len - 2; i >= 0; i--) {
            if (ratings[i] > ratings[i + 1]) {
                candyVec[i] = Math.max(candyVec[i], candyVec[i + 1] + 1);
            }
        }

        int ans = 0;
        for (int num : candyVec) {
            ans += num;
        }
        return ans;
    }
}

2、C++

c 复制代码
class Solution {
public:
    int candy(vector<int>& ratings) {
        vector<int> candyVec(ratings.size(), 1);
        // 从前向后
        for (int i = 1; i < ratings.size(); i++) {
            if (ratings[i] > ratings[i - 1]) candyVec[i] = candyVec[i - 1] + 1;
        }
        // 从后向前
        for (int i = ratings.size() - 2; i >= 0; i--) {
            if (ratings[i] > ratings[i + 1] ) {
                candyVec[i] = max(candyVec[i], candyVec[i + 1] + 1);
            }
        }
        // 统计结果
        int result = 0;
        for (int i = 0; i < candyVec.size(); i++) result += candyVec[i];
        return result;
    }
};

3、python

python 复制代码
class Solution:
    def candy(self, ratings: List[int]) -> int:
        candyVec = [1] * len(ratings)
        
        # 从前向后遍历,处理右侧比左侧评分高的情况
        for i in range(1, len(ratings)):
            if ratings[i] > ratings[i - 1]:
                candyVec[i] = candyVec[i - 1] + 1
        
        # 从后向前遍历,处理左侧比右侧评分高的情况
        for i in range(len(ratings) - 2, -1, -1):
            if ratings[i] > ratings[i + 1]:
                candyVec[i] = max(candyVec[i], candyVec[i + 1] + 1)
        
        # 统计结果
        result = sum(candyVec)
        return result

4、go

go 复制代码
func candy(ratings []int) int {
    /**先确定一边,再确定另外一边
        1.先从左到右,当右边的大于左边的就加1
        2.再从右到左,当左边的大于右边的就再加1
    **/
    need := make([]int, len(ratings))
    sum := 0
    // 初始化(每个人至少一个糖果)
     for i := 0; i < len(ratings); i++ {
         need[i] = 1
     }
     // 1.先从左到右,当右边的大于左边的就加1
    for i := 0; i < len(ratings) - 1; i++ {
        if ratings[i] < ratings[i+1] {
            need[i+1] = need[i] + 1
        }
    }
    // 2.再从右到左,当左边的大于右边的就右边加1,但要花费糖果最少,所以需要做下判断
    for i := len(ratings)-1; i > 0; i-- {
        if ratings[i-1] > ratings[i] {
            need[i-1] = findMax(need[i-1], need[i]+1)
        }
    }
    //计算总共糖果
    for i := 0; i < len(ratings); i++ {
        sum += need[i]
    }
    return sum
}
func findMax(num1 int, num2 int) int {
    if num1 > num2 {
        return num1
    }
    return num2
}
相关推荐
叫我:松哥21 小时前
基于神经网络算法的多模态内容分析系统,采用Flask + Bootstrap + ECharts + LSTM-CNN + 注意力机制
前端·神经网络·算法·机器学习·flask·bootstrap·echarts
每天学一点儿21 小时前
【医学图像处理】SimpleITK 图像配准全流程解析
算法
不穿格子的程序员21 小时前
从零开始写算法——回溯篇1:全排列 + 子集
算法·leetcode·深度优先·回溯
Yupureki21 小时前
《算法竞赛从入门到国奖》算法基础:入门篇-贪心算法(下)
c语言·c++·学习·算法·贪心算法
zzz海羊1 天前
【CS336】Transformer|2-BPE算法 -> Tokenizer封装
深度学习·算法·语言模型·transformer
_OP_CHEN1 天前
【算法基础篇】(四十七)乘法逆元终极宝典:从模除困境到三种解法全解析
c++·算法·蓝桥杯·数论·算法竞赛·乘法逆元·acm/icpc
杭州杭州杭州1 天前
pta考试
数据结构·c++·算法
YuTaoShao1 天前
【LeetCode 每日一题】2975. 移除栅栏得到的正方形田地的最大面积
算法·leetcode·职场和发展
少许极端1 天前
算法奇妙屋(二十五)-递归问题
算法·递归·汉诺塔
Remember_9931 天前
【数据结构】初识 Java 集合框架:概念、价值与底层原理
java·c语言·开发语言·数据结构·c++·算法·游戏