代码随想录算法训练营33期 第三十六天 |435. 无重叠区间、763.划分字母区间、56. 合并区间

435. 无重叠区间

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) {
        sort(intervals.begin(), intervals.end(), cmp);
        int result=0;
        for (int i=1; i<intervals.size(); i++){
            if (intervals[i][0] < intervals[i-1][1]){  //发生重叠
                result++;
                intervals[i][1]= min(intervals[i][1], intervals[i-1][1]);
            }
        }
        return result;
    }
};

这道题比想象中更巧妙,我觉得和上一道题射气球其实不一样。
射气球维护的是一个重叠区间范围,所以每次都将上一个区间的右边界维护为最小的那个,保证这个区间内的元素都是重叠的,如果超过了上一个最大右边界的右区间就说明当前元素和上一个最大区间不能合并,必须增加一支箭。

对于本题,我觉得维护最大重叠区域范围的思路并不好想,看了评论区才明白,intervals[i][1]= min(intervals[i][1], intervals[i-1][1]);删除的优先级是1、当前区间和上一个区间中最大的那一个,2、当前区间。
为什么是这样?
因为我们首先对所有区间根据左起始点进行了排序,之后发生重叠时,将当前元素的右区间更新为当前区域右端点和上一个元素右端点的最大值。如果当前右端点比上一个右端点要靠左,说明上一个区间肯定比当前区间长,因为已经排序了,上一个区间的左端点已经更小了,并且其右端点更大,说明上一个区间比较长。因为题干要求是删除最少的区间数量,那我们肯定优先删除长的那个。所以将当前区间保留。

763.划分字母区间

class Solution {
public:
    vector<int> partitionLabels(string s) {
        vector<int> hash(27, 0);
        vector<int> result;
        for (int i=0; i<s.size(); i++){
            hash[s[i]-'a'] = i;
        }
        int left=0, right=0;
        for (int i=0; i<s.size(); i++){
            right = max(hash[s[i]-'a'], right); //记录当前区间中最远元素位置
            if (right==i) //到达当前区间中最远元素,说明当前区间内的元素都在这个left right这个范围内了
            {
                result.push_back(right-left+1);
                left = i+1;
            }
        }
        return result;
    }
};

理解题干比写代码难。

56. 合并区间

class Solution {
public:
    static bool cmp(vector<int> a, vector<int> b){
        return a[0]<b[0];
    }
    vector<vector<int>> merge(vector<vector<int>>& intervals) {
        sort(intervals.begin(), intervals.end(), cmp);
        vector<vector<int>> result;
        result.push_back(intervals[0]);
        for (int i=1; i<intervals.size(); i++){
            if (intervals[i][0]<=result.back()[1]){
                result.back()[1] = max(result.back()[1], intervals[i][1]); //更新右端点
            }
            else{ //保存独立区间
                result.push_back(intervals[i]);
            }
        }
        return result;
    }
};

直接更新result中的内容还是第一次见。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值