当前位置: 首页 > article >正文

DAY30|贪心算法Part04|LeetCode:452. 用最少数量的箭引爆气球、435. 无重叠区间、763.划分字母区间

目录

LeetCode:452. 用最少数量的箭引爆气球

基本思路

C++代码

LeetCode:435. 无重叠区间

基本思路

C++代码

LeetCode:763.划分字母区间

基本思路

C++代码


LeetCode:452. 用最少数量的箭引爆气球

力扣代码链接

文字讲解:LeetCode:452. 用最少数量的箭引爆气球

视频讲解:贪心算法,判断重叠区间问题

基本思路

        首先我们应该先对气球进行排序,这样才能保证让气球尽可能重叠,因为只有重叠的时候我们才能用更少的箭去射爆气球。那么按照气球起始位置排序,还是按照气球终止位置排序呢?

        其实都可以!只不过对应的遍历顺序不同,我就按照气球的起始位置排序了。既然按照起始位置排序,那么就从前向后遍历气球数组,靠左尽可能让气球重复。

        从前向后遍历遇到重叠的气球了怎么办?如果气球重叠了,重叠气球中右边边界的最小值之前的区间一定需要一个弓箭。以例一为例:

        可以看出首先第一组重叠气球,一定是需要一个箭,气球3,的左边界大于了 第一组重叠气球的最小右边界,所以再需要一支箭来射气球3了。

C++代码

class Solution {
private:
    static bool cmp(const vector<int>& a, const vector<int>& b) {
        return a[0] < b[0];
    }
public:
    int findMinArrowShots(vector<vector<int>>& points) {
        if (points.size() == 0) return 0;
        sort(points.begin(), points.end(), cmp);

        int result = 1; // points 不为空至少需要一支箭
        for (int i = 1; i < points.size(); i++) {
            if (points[i][0] > points[i - 1][1]) {  // 气球i和气球i-1不挨着,注意这里不是>=
                result++; // 需要一支箭
            }
            else {  // 气球i和气球i-1挨着
                points[i][1] = min(points[i - 1][1], points[i][1]); // 更新重叠气球最小右边界
            }
        }
        return result;
    }
};

        这里points[i][1] = min(points[i - 1][1], points[i][1]); 是为了更新重叠气球的最小右边界,这样的话对于下一次循环过程中,第i+1个气球如果和更新边界后的第i个气球不存在重叠区域,那么就不存在一支箭射爆三个气球的情况。

LeetCode:435. 无重叠区间

力扣代码链接

文字讲解:LeetCode:435. 无重叠区间

视频讲解:贪心算法,依然是判断重叠区间

基本思路

        这个题目和上一题有些相似,都是需要判断区间是否重叠,此时应该按照左边界进行排序还是右边界进行排序呢?其实都可以。主要就是为了让区间尽可能的重叠。

        按照左边界进行排序,我们依旧按照从前向后进行遍历,如果遍历到当前区间的起始位置大于上一个区间的终止位置就说明存在重叠区间,即进行记录。

        另外我们还需要对两个区间的终止位置进行比较,取最小值并赋给变量end,end就是区间分割点,这样当和下个区间相比较时,就可以判断三个区间是否存在公共区间,并且用count用来记录重叠区间的个数。

C++代码

class Solution {
public:
    static bool cmp (const vector<int>& a, const vector<int>& b) {
        return a[0] < b[0]; // 改为左边界排序
    }
    int eraseOverlapIntervals(vector<vector<int>>& intervals) {
        if (intervals.size() == 0) return 0;
        sort(intervals.begin(), intervals.end(), cmp);
        int count = 0; // 注意这里从0开始,因为是记录重叠区间
        int end = intervals[0][1]; // 记录区间分割点
        for (int i = 1; i < intervals.size(); i++) {   
            if (intervals[i][0] >= end)  end = intervals[i][1]; // 无重叠的情况
            else { // 重叠情况 
                end = min(end, intervals[i][1]);
                count++;
            }
        }
        return count;
    }
};

LeetCode:763.划分字母区间

力扣代码链接

文字讲解:LeetCode:763.划分字母区间

视频讲解:贪心算法,寻找最远的出现位置!

基本思路

        题目要求同一字母最多出现在一个片段中,难点在于如何把同一个字母的都圈在同一个区间里呢?在遍历的过程中相当于是要找每一个字母的边界,如果找到之前遍历过的所有字母的最远边界,说明这个边界就是分割点了。此时前面出现过所有字母,最远也就到这个边界了。

        可以分为如下两步:

  • 统计每一个字符最后出现的位置
  • 从头遍历字符,并更新字符的最远出现下标,如果找到字符最远出现位置下标和当前下标相等了,则找到了分割点

C++代码

class Solution {
public:
    vector<int> partitionLabels(string S) {
        int hash[27] = {0}; // i为字符,hash[i]为字符出现的最后位置
        for (int i = 0; i < S.size(); i++) { // 统计每一个字符最后出现的位置
            hash[S[i] - 'a'] = i;
        }
        vector<int> result;
        int left = 0;
        int right = 0;
        for (int i = 0; i < S.size(); i++) {
            right = max(right, hash[S[i] - 'a']); // 找到字符出现的最远边界
            if (i == right) {
                result.push_back(right - left + 1);
                left = i + 1;
            }
        }
        return result;
    }
};

http://www.kler.cn/a/400304.html

相关文章:

  • 基于 MONAI 的 3D 图像分割任务2(Brain Tumour 和 SwinUNETR 训练)
  • 基于yolov8、yolov5的行人检测识别系统(含UI界面、训练好的模型、Python代码、数据集)
  • Java-异步方法@Async+自定义分布式锁注解Redission例子
  • RabbitMQ教程:发布/订阅模式(Publish/Subscribe)(三)
  • Debezium日常分享系列之:Debezium3版本Debezium connector for JDBC
  • 【代码pycharm】动手学深度学习v2-05 线性代数
  • 【C++】用哈希表封装unordered_map和unordered_set
  • uni-app快速入门(十一)--常用JS API(上)
  • 全志科技嵌入式面试题及参考答案
  • 【论文阅读】Large Language Models for Equivalent Mutant Detection: How Far Are We?
  • vue3 + vite + ts 配置 @ 别名
  • python成长技能之正则表达式
  • python模块和包
  • 【漏洞复现】某全新H5购物商城系统存在前台任意文件上传漏洞(RCE)
  • 枚举Enum使用
  • # ubuntu安装openjdk 和 pycharm 并解决 pycharm 不能输入中文的问题
  • 有限状态机(续)
  • 跨平台WPF框架Avalonia教程 十
  • Spring Boot出现java: 错误: 无效的源发行版:16的解决方式
  • 缓存与数据库不一致的解决方案:深入理解与实践
  • Prometheus结合K8s(二)使用
  • Linux多线程(线程池与单例模式)
  • Java项目实战II基于Java+Spring Boot+MySQL的共享汽车管理系统(源码+数据库+文档)
  • uniapp 设置form表单以及验证密码
  • SQL,力扣题目1369,获取最近第二次的活动
  • uniapp Uview上传图片组件Upload会自动刷新