代码随想录day30贪心算法4

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

题目链接
文章讲解

class Solution {
public:
    static bool cmp(const vector<int>& a, const vector<int>& b) {
        if (a[1] == b[1]) return a[0] < b[0];  // 按照结束位置升序排列,若结束位置相同,按开始位置升序排列
        return a[1] < b[1];  // 根据气球的结束位置排序
    }

    int findMinArrowShots(vector<vector<int>>& points) {
        // 如果没有气球,返回 0
        if (points.empty()) return 0;
        
        // 对气球按照结束位置排序
        sort(points.begin(), points.end(), cmp);
        
        int ans = 1;  // 至少需要一支箭
        int k = points[0][1];  // 第一支箭的位置是第一个气球的结束位置
        
        // 从第二个气球开始遍历
        for (int i = 1; i < points.size(); i++) {
            // 如果当前气球的起始位置大于上一支箭的结束位置,说明它们不重叠,需要新的一支箭
            if (points[i][0] > k) {
                ans++;  // 新的箭
                k = points[i][1];  // 更新箭的位置为当前气球的结束位置
            }
        }
        
        return ans;  // 返回最少箭矢数量
    }
};

435. 无重叠区间

题目链接
文章讲解

class Solution {
public:
    // 比较函数:按照区间的结束时间进行升序排序
    static bool cmp(const vector<int>& a, const vector<int>& b) {
        return a[1] < b[1];  // 比较区间的结束时间,升序排列
    }

    int eraseOverlapIntervals(vector<vector<int>>& intervals) {
        // 对区间进行排序,排序规则是按照结束时间升序排列
        sort(intervals.begin(), intervals.end(), cmp);

        int ans = 0;  // 用于记录需要删除的区间数
        int k = intervals[0][1];  // 初始化当前区间的结束时间为第一个区间的结束时间
        
        // 从第二个区间开始遍历
        for (int i = 1; i < intervals.size(); i++) {
            // 如果当前区间的起始时间小于前一个区间的结束时间,说明有重叠
            if (k > intervals[i][0]) {
                ans++;  // 增加删除的区间数
            } else {
                // 如果没有重叠,更新当前区间的结束时间
                k = intervals[i][1];
            }
        }

        return ans;  // 返回删除的区间数
    }
};

763.划分字母区间

题目链接
文章讲解

class Solution {
public:
    // 该比较函数记录字符在字符串中最后一次出现的索引
    vector<int> partitionLabels(string s) {
        const int N = 1e5;  // 假设足够大的数组大小
        int a[N];  // 用于记录每个字符在字符串中的最后一次出现的位置
        memset(a, 0, sizeof(a));  // 初始化数组为 0
        
        // 遍历字符串,记录每个字符的最后出现位置
        for (int i = 0; i < s.size(); i++) {
            a[s[i]] = i;  // 存储字符s[i]最后出现的位置
        }
        
        int max1 = a[s[0]];  // 初始最大右边界为第一个字符的最后位置
        vector<int> v;  // 存储最终的分割区间的长度
        int pre = -1;  // 记录上一个分割点的位置
        
        // 遍历字符串,根据最大右边界划分子字符串
        for (int i = 0; i < s.size(); i++) {
            max1 = max(max1, a[s[i]]);  // 更新当前子字符串的最大右边界
            
            // 如果当前索引 i 达到最大右边界,说明可以确定一个子字符串
            if (i == max1) {
                v.push_back(i - pre);  // 计算当前子字符串的长度并加入结果
                max1 = 0;  // 重置最大右边界
                pre = i;  // 更新分割点为当前的索引
            }
        }
        
        return v;  // 返回所有子字符串的长度
    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值