• 算法通关村-----原来贪心如此简单


    贪心思想

    贪心本质上是花费更少的资源获得更多的收益,在解决问题时,我们希望在每一步中都进行最优的选择,从而的到最优的结果。其实贪心并不总是能得到最优的结果,但是可以得到近似最优解,如果我们对最优结果的要求并不高,但是希望时间成本小一些,贪心往往是一个不错的选择。什么时候应该考虑使用贪心呢,是当问题具有最优子结构的时候,但是最优子结构这个问题比较复杂,我们可以从题目中寻找贪心的规律。

    分发饼干

    问题描述

    假设你是一位很棒的家长,想要给你的孩子们一些小饼干。但是,每个孩子最多只能给一块饼干。 对每个孩子 i,都有一个胃口值 g[i],这是能让孩子们满足胃口的饼干的最小尺寸;并且每块饼干 j,都有一个尺寸 s[j] 。如果 s[j] >= g[i],我们可以将这个饼干 j 分配给孩子 i ,这个孩子会得到满足。你的目标是尽可能满足越多数量的孩子,并输出这个最大数值。详见leetcode455

    问题分析

    每个孩子最多只能给一块饼干,我们希望的每一步的最优解,就是将当前最大尺寸的饼干,分配给该饼干能满足的最大胃口的孩子,这样可以避免“大饼干”分配给“胃口小孩子”的浪费。

    代码实现

    public int findContentChildren(int[] g, int[] s) {
        Arrays.sort(g);
        Arrays.sort(s);
        int j = s.length-1;
        int count = 0;
        for(int i=g.length-1;i>=0;i--){
            if(j>=0 && s[j]>=g[i]){
                count++;
                j--;
            }
        }
        return count;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    柠檬水找零

    问题描述

    在柠檬水摊上,每一杯柠檬水的售价为 5 美元。顾客排队购买你的产品,(按账单 bills 支付的顺序)一次购买一杯。每位顾客只买一杯柠檬水,然后向你付 5 美元、10 美元或 20 美元。你必须给每个顾客正确找零,也就是说净交易是每位顾客向你支付 5 美元。注意,一开始你手头没有任何零钱。给你一个整数数组 bills ,其中 bills[i] 是第 i 位顾客付的账。如果你能给每位顾客正确找零,返回 true ,否则返回 false 。详见leetcode860

    问题分析

    如果是五元,直接收下,如果是十元,用五元找零,如果是二十元,可以用一张十元加一张五元或者三张五元找零。当收到一张二十元时,应该如何处理呢,很明显,如果有十元,用一张十元加一张五元,否则三张五元,这就是我们每一步的最优解

    代码实现

    public boolean lemonadeChange(int[] bills) {
        int cash5 = 0;
        int cash10 = 0;
        for(int i=0;i<bills.length;i++){
            if(bills[i]==5){
                cash5++;
            }else if(bills[i]==10){
                if(cash5>=1){
                    cash10++;
                    cash5--;
                }else{
                    return false;
                }
            }else{
                if(cash10>=1&&cash5>=1){
                    cash10--;
                    cash5--;
                }else if(cash5>=3){
                    cash5-=3;
                }else{
                    return false;
                }
            }
        }
        return true;
    }
    
    • 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

    分发糖果

    问题描述

    n 个孩子站成一排。给你一个整数数组 ratings 表示每个孩子的评分。你需要按照以下要求,给这些孩子分发糖果:

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

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

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

    问题分析

    如果两个相邻评分不等,则一个孩子比另一个孩子多一个糖果,如果两个孩子评分相等,则给第二个孩子一颗糖果,这就是每一次的最优解,如果直接按照规则,需要不断比较一个孩子的评分和两侧孩子的评分,我们可以通过两次遍历实现,第一次,设置第一个孩子一颗糖果,后面如果评分递增,则分配给孩子多一个糖果,否则,只给一个糖果,然后从倒数第二个孩子向前遍历,如果比后一个孩子评分高,则增加一个糖果,只是第二次遍历需要同时考虑两侧,所以取两者的较大值即可。

    代码实现

    public int candy(int[] ratings) {
        int[] nums = new int[ratings.length];
        nums[0] = 1;
        int count = 0;
        for(int i=1;i<nums.length;i++){
            if(ratings[i]>ratings[i-1]){
                nums[i] = nums[i-1]+1;
            }else{
                nums[i] = 1;
            }
        }
        for(int i=nums.length-2;i>=0;i--){
            if(ratings[i]>ratings[i+1]){
                nums[i] = Math.max(nums[i+1]+1,nums[i]);
            }
        }
        for(int i=0;i<nums.length;i++){
            count+=nums[i];
        }
        return count;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
  • 相关阅读:
    Rockland丨GOAT TRUEBLOT抗山羊IGG HRP说明书
    C#学习记录——数据流
    ContentProvider的执行时机
    React基于monaco editor的在线代码编辑器开发
    AOC新特性发布会之事件中心
    算数运算符 与 逻辑运算符
    关于Request复用的那点破事儿。研究明白了,给你汇报一下。
    db-cdc之mysql 深入了解并使用binlog
    Sikuli 基于图形识别的自动化测试技术
    ElasticSearch 本地快速搭建与使用
  • 原文地址:https://blog.csdn.net/m0_45362454/article/details/132731591