• 贪心 Leetcode 135 分发糖果


    分发糖果

    Leetcode 135

    学习记录自代码随想录

    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

    要点:1.从左到右遍历时关注右比左小的情况,情况处理较为复杂,进而联想到再一次从右到左遍历简化判断;

    方法一:单纯从左到右遍历

    class Solution {
    public:
        int candy(vector<int>& ratings) {
            int result = 0;;
            int pre_diff = 0;
            int cur_diff = 0;
            vector<int> sugar_num(ratings.size(), 1);
    
            if(ratings.size() == 1) return 1;
            for(int i = 1; i < ratings.size(); i++){
                cur_diff = ratings[i] - ratings[i-1];
                if(cur_diff > 0){
                    sugar_num[i] = sugar_num[i-1] + 1;
                // [0,1,2,3,2,1]
                }else if(i >=2 && cur_diff < 0 && pre_diff < 0){
                    int cnt = 0;
                    while(cnt < i && ratings[i-cnt] < ratings[i-cnt-1]){
                        // 使用max减少了判断条件 && sugar_num[i-cnt] >= sugar_num[i-cnt-1]
                        sugar_num[i-cnt-1] = max(sugar_num[i-cnt-1], sugar_num[i-cnt] + 1);
                        cnt += 1;
                    }
                // [1,2,87,87,87,2,1]
                }else if(cur_diff < 0 && pre_diff == 0){
                    sugar_num[i-1] += 1;
                }
                pre_diff = cur_diff;
            }
    
            for(int a : sugar_num) result += a;      
    
            return result;
        }
    };
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    方法二:两次遍历,分别从左到右和从右到左
    // 两次贪心的策略:
    // 一次是从左到右遍历,只比较右边孩子评分比左边大的情况。
    // 一次是从右到左遍历,只比较左边孩子评分比右边大的情况。

    class Solution{
    public:
        int candy(vector<int>& ratings){
            vector<int> sugar_num(ratings.size(), 1);
            int result = 0;
    
            if(ratings.size() == 1) return 1;
            // 两次贪心的策略:
            // 一次是从左到右遍历,只比较右边孩子评分比左边大的情况。
            // 一次是从右到左遍历,只比较左边孩子评分比右边大的情况。
            // 从左到右遍历
            for(int i = 1; i < ratings.size(); i++){
                if(ratings[i] > ratings[i-1]){
                    sugar_num[i] = sugar_num[i-1] + 1;
                }
            }
            // 从右到左遍历
            for(int i = ratings.size()-1; i >= 1; i--){
                if(ratings[i] < ratings[i-1]){
                    // 贪心
                    sugar_num[i-1] = max(sugar_num[i-1], sugar_num[i] + 1); 
                }
            }
    
            for(int a : sugar_num) result += a;
    
            return result;
        }
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
  • 相关阅读:
    计算机毕设 机器学习新闻算法实现 - python机器学习 深度学习
    C# 快速排序
    单目3D目标检测——MonoDLE 模型训练 | 模型推理
    无刷直流电机(BLDC)
    问题 A: 二叉排序树 - 文本输出
    【网络安全】护网
    RTU远程终端控制系统S274
    策略路由(本地策略和接口策略)
    Golang源码:singleflight分析(二)
    云存储应急演练体系建立及场景设计
  • 原文地址:https://blog.csdn.net/weixin_46930685/article/details/136463373