首页 > 其他分享 >【LeetCode贪心#07】分糖果

【LeetCode贪心#07】分糖果

时间:2023-03-17 16:34:19浏览次数:46  
标签:ratings 右边 遍历 07 孩子 candyCount 糖果 LeetCode 贪心

发糖果

力扣题目链接(opens new window)

老师想给孩子们分发糖果,有 N 个孩子站成了一条直线,老师会根据每个孩子的表现,预先给他们评分。

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

  • 每个孩子至少分配到 1 个糖果。
  • 相邻的孩子中,评分高的孩子必须获得更多的糖果。

那么这样下来,老师至少需要准备多少颗糖果呢?

示例 1:

  • 输入: [1,0,2]
  • 输出: 5
  • 解释: 你可以分别给这三个孩子分发 2、1、2 颗糖果。

示例 2:

  • 输入: [1,2,2]
  • 输出: 4
  • 解释: 你可以分别给这三个孩子分发 1、2、1 颗糖果。第三个孩子只得到 1 颗糖果,这已满足上述两个条件。

思路

根据示例1、2来看,我们只需要对满足规则的两种情况发放糖果即可,目标是在满足规则的前提下消耗最少的糖果(因此发的糖果数量有可能是不公平的)

怎么做呢?其实也简单,就是遍历数组,比较前后元素的大小关系,由此分配糖果即可

但是细想一下,遍历过程也是有坑的

举个例子:

从左往右遍历ratings数组,得到每个小孩应该分配的糖果数【左边孩子与右边孩子相比得出的结果】

此时的贪心:

局部最优:只要右边评分比左边大(ratings[i] > ratings[i - 1]),右边的孩子就多一个糖果

全局最优:相邻的孩子中,评分高的右孩子获得比左边孩子更多的糖果

//从左往右遍历ratings数组,左边孩子与右边孩子相比
for(int i = 1; i < ratings.size(); ++i){//从下标1开始
    if((ratings[i] > ratings[i - 1]) candyCount[i] = candyCount[i - 1] + 1;
}

但是,下标4和5位置,下标5的评分比4低,但是获得的糖果数一样,这不满足规则

所以还要从右往左遍历一遍【右边孩子与左边孩子相比得出的结果】,综合之后取最大值得出要分配的糖果数

此时的贪心:

局部最优:只要左边评分比右边大(ratings[i] > ratings[i + 1]),左边的孩子就多一个糖果

全局最优:相邻的孩子中,评分高的左孩子获得比右边孩子更多的糖果

//从右往左遍历ratings数组,右边孩子与左边孩子相比
for(int i = ratings.size() - 2; i >= 0; --i){//从倒数第二个下标开始
    if(ratings[i] > ratings[i + 1]){
        candyCount[i] = max(candyCount[i + 1] + 1, candyCount[i]);//取当前糖果数与之前的最大值
    }        
}

注意:将右边孩子和左边孩子相比时,必须从右往左遍历,不能从左往右然后通过改下标的方式来比较

代码

本题仍然采用了两次贪心策略

  • 一次是从左到右遍历,只比较右边孩子评分比左边大的情况。
  • 一次是从右到左遍历,只比较左边孩子评分比右边大的情况。

两次贪心最终可以得到满足规则的糖果分配数

步骤如下:

1、创建糖果数统计数组

2、从左往右遍历ratings数组,左边孩子与右边孩子相比

3、从右往左遍历ratings数组,右边孩子与左边孩子相比

4、统计糖果数

class Solution {
public:
    int candy(vector<int>& ratings) {
        //定义糖果统计数组
        vector<int> candyCount(ratings.size(), 1);//默认给一个糖
        //从左往右遍历ratings数组,左边孩子与右边孩子相比
        for(int i = 1; i < ratings.size(); ++i){//从下标1开始
            if(ratings[i] > ratings[i - 1]) candyCount[i] = candyCount[i - 1] + 1;
        }

        //从右往左遍历ratings数组,右边孩子与左边孩子相比
        for(int i = ratings.size() - 2; i >= 0; --i){//从倒数第二个下标开始
            if(ratings[i] > ratings[i + 1]){
                candyCount[i] = max(candyCount[i + 1] + 1, candyCount[i]);
            }
        }
        //统计糖果数
        int res = 0;
        for(int c : candyCount) res += c;
        return res;
    }
};

标签:ratings,右边,遍历,07,孩子,candyCount,糖果,LeetCode,贪心
From: https://www.cnblogs.com/DAYceng/p/17227238.html

相关文章

  • LeetCode|412. Fizz Buzz
    题目链接:412.FizzBuzz给你一个整数n,找出从1到n各个整数的FizzBuzz表示,并用字符串数组answer(下标从1开始)返回结果,其中:answer[i]=="FizzBuzz"如果i......
  • LeetCode|1672. 最富有客户的资产总量
    题目链接:1672.最富有客户的资产总量难度简单173收藏分享切换为英文接收动态反馈给你一个mxn的整数网格accounts,其中accounts[i][j]是第i位客户在第j家银......
  • 【LeetCode贪心#06】加油站(股票买卖变种)
    加油站力扣题目链接(opensnewwindow)在一条环路上有N个加油站,其中第i个加油站有汽油gas[i]升。你有一辆油箱容量无限的的汽车,从第i个加油站开往第i+1个加油......
  • 代码随想录Day2-Leetcode977.有序数组的平方 ,209.长度最小的子数组 ,59.螺旋矩阵II
    977.有序数组的平方题目链接:https://leetcode.cn/problems/squares-of-a-sorted-array/最初想法是用二分找到恰好大于0的数;然后数组切片,负的一方反转,然后按照合并......
  • LeetCode1. 两数之和
    题目描述:给定一个整数数组nums 和一个整数目标值target,请你在该数组中找出和为目标值target 的那 两个 整数,并返回它们的数组下标。你可以假设每种输入只会对应......
  • 【leetcode】226.翻转二叉树
    翻转二叉树leetcode题目传送门题目描述思路按顺序依次交换二叉树的左右节点实现交换左右节点,递归遍历publicclassTreeNode{publicintval;......
  • LeetCode 18. 四数之和
    classSolution{public:vector<vector<int>>fourSum(vector<int>&nums,inttarget){vector<vector<int>>ans;longlongtmp=target;......
  • LeetCode1024 -- 二分
    1.题目描述查找满足劳累天数严格大于不劳累天数的最大子区间2.思路对于区间问题,很容易先想到前缀和帮助我们优化。我们可以设,劳累=\(1\),不劳累=\(-1\),那么,就是求......
  • Leetcode202. 快乐数
    题目描述:编写一个算法来判断一个数n是不是快乐数。「快乐数」 定义为:•对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和。•然后重复这个过程直到这个......
  • 007 性能指标
    计算最大线程数查询功能,需要系统能够在5分钟内能完成5000笔查询业务,同时用户响应时间不超过3s,该用多少线程数施压?公式:最大线程数=(单次响应时间*业务量)/总的业务......