【LeetCode刷题】贪心算法(一)

贪心算法

贪心算法或贪心思想采用贪心的策略,保证每次操作都是局部最优的,从而使最后得到的结果是全局最优的。

455 分发饼干

题目表述

(简单)
假设你是一位很棒的家长,想要给你的孩子们一些小饼干。但是,每个孩子最多只能给一块饼干。

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

比如:你有三个孩子和两块小饼干,3个孩子的胃口值分别是:1,2,3。虽然你有两块小饼干,由于他们的尺寸都是1,你只能让胃口值是1的孩子满足。所以你应该输出1。

题解:

class Solution {
public:
    int findContentChildren(vector<int>& g, vector<int>& s) {
        // 首先将孩子的胃口与饼干尺寸都按照从小到大进行排序
        sort(g.begin(), g.end());
        sort(s.begin(), s.end());
        // 定义初始值
        int child = 0;
        int cookie = 0;
        // 从小到大开始遍历,使用较小的饼干优先满足胃口较小的孩子
        // 如果
        while(child < g.size() && cookie < s.size()) {
            if(g[child] <= s[cookie]) ++child;
            ++cookie;
        }
        return child;
    }
};

435 无重叠区间

题目表述

(中等)
给定一个区间的集合,找到需要移除区间的最小数量,使剩余区间互不重叠。

注意:
可以认为区间的终点总是大于它的起点。
区间 [1,2] 和 [2,3] 的边界相互“接触”,但没有相互重叠。

题解

class Solution {
public:
    int eraseOverlapIntervals(vector<vector<int>>& intervals) {
        // 如果输入为空则返回空
        if (intervals.empty()){
            return 0;
        }
        int n = intervals.size();
        // 对输入的区间进行排序,排序方式为按照区间右边从小到大进行排序
        // 使用Lambda方式定义排序方式
        // Lambda 表达式的定义形式为[外部变量访问方式说明符] (参数表) -> 返回值类型{语句块}
        sort(intervals.begin(), intervals.end(), [](vector<int>& a, vector<int>& b){
            return a[1]<b[1];
        });
        // 定义初始值,初始化为第一个区间
        int total = 0, prev = intervals[0][1];
        // 进行遍历,如果后一个区间的左值小于前一个区间的右值,则需要去除,否则将更新prev
        for (int i = 1; i<n; i++){
            if(intervals[i][0] < prev){
                total++;
            }else{
                prev = intervals[i][1];
            }
        }
        return total;
    }
};

135 分发糖果

题目描述

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

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

每个孩子至少分配到 1 个糖果。
评分更高的孩子必须比他两侧的邻位孩子获得更多的糖果。

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

题解

把所有孩子的糖果数初始化为 1;先从左往右遍历一遍,如果右边孩子的评分比左边的高,则右边孩子的糖果数更新为左边孩子的糖果数加 1;再从右往左遍历一遍,如果左边孩子的评分比右边的高,且左边孩子当前的糖果数不大于右边孩子的糖果数,则左边孩子的糖果数更新为右边孩子的糖果数加 1。

class Solution {
public:
    int candy(vector<int>& ratings) {
        // 只有一个孩子即返回一个
        int size = ratings.size();
        if(size < 2){
            return size;
        }
        // 初始化为长度为size,值为1的数组
        vector<int> num(size, 1);
        // 从左往右遍历,如果右边孩子的评分比左边的高,则右边孩子的糖果数更新为左边孩子的糖果数加1
        for(int i = 1; i < size; i++){
            if(ratings[i] > ratings[i-1]){
                num[i] = num[i-1] + 1;
            }
        }
        // 从右往左遍历,如果左边孩子的评分比右边的高,且左边孩子当前的糖果数不大于右边孩子的糖果数,
        // 则左边孩子的糖果数更新为右边孩子的糖果数加1
        for(int i = size - 1; i > 0; i--){
            if(ratings[i] < ratings[i-1]){
                // 直接返回左边孩子当前的糖果数与右边孩子的糖果数加1的最大值
                num[i-1] = max(num[i-1], num[i] + 1);
                // num[i] = num[i-1] + 1;
            }
        }
        // 对数组所有的元素进行相加得出结果
        return accumulate(num.begin(), num.end(), 0);
        //accumulate定义在#include<numeric>,第三个参数是初值
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值