一、LeetCode 435. 无重叠区间
题目链接/文章讲解/视频讲解:https://programmercarl.com/0435.%E6%97%A0%E9%87%8D%E5%8F%A0%E5%8C%BA%E9%97%B4.html
状态:已解决
1.思路
本题的局部最优是尽量移除与某个区间重叠的其他区间,全局最优是移除的区间数最少,局部最优可以推出全局最优,因此可以贪心。如图

这种情况当然就只移除第二个区间,这样就刚好使得剩下的区间不重叠。

这种情况无论如何都至少要移除两个区间。因此对于k个重叠区间,最少都需要移除(k-1)个区间,才能使得剩余区间并不重叠。
因此,此题和452题思路都一致,就是寻找重叠区间,只是这题重叠区间要保留一份,而452题是重叠区间用一只箭射掉,二者统计得到的数量是一致的。故求未重叠的区间的数量的代码是一模一样的,本题再用所有区间的数量-未重叠区间的数量,就能得到要移除的重叠区间的数量。
2.代码实现
class Solution {
public:
    static bool cmp(const vector<int>& v1, const vector<int>& v2){
    //第一元素相等时,再比较第二元素
        if (v1[0] == v2[0])
            return v1[1] < v2[1];
        return v1[0] < v2[0];
    }
    int eraseOverlapIntervals(vector<vector<int>>& intervals) {
        int num = 1;
        sort(intervals.begin(),intervals.end(),cmp);
        for(int i=1;i<intervals.size();i++){
            if(intervals[i][0]>=intervals[i-1][1]){
                num++;
            }else{
                intervals[i][1] = min(intervals[i][1],intervals[i-1][1]);
            }
        }
        return intervals.size()-num;//相当于452题多出了一步求移除区间的数量,二题是对称的
    }
};二、 763.划分字母区间
题目链接/文章讲解/视频讲解:https://programmercarl.com/0763.%E5%88%92%E5%88%86%E5%AD%97%E6%AF%8D%E5%8C%BA%E9%97%B4.html
状态:已解决
1.思路
一般说到分割字符串问题,我们下意识就想到回溯算法,但回溯算法效率较低,一般还是优先采用效率较高的算法。此题就可以不用回溯。
此题要求同一字母最多出现在同一个片段中,那么如何保证某个字母只出现在同一个片段中呢?很简单,我们在划分片段的时候,就选取这个字母第一次出现的位置和它最远出现的位置,这样划分出来的其他片段就不会存在该字母了。如果在这个划分区间内,有其他字母出现,那么这个片段的右边界就不一定取这个字母的最远位置了,而是取这个字母开始位置到这个字母的最远位置之间,所有字母的最远位置的最大值。如图:

此时取得是a的起始位置和c的最远位置。
想明白这个点,接下来就很好处理了,可以分为如下两步:
- 统计每一个字符最后出现的位置
- 从头遍历字符,并更新字符的最远出现下标,如果找到字符最远出现位置下标和当前下标相等了,则找到了分割点

2.代码实现
class Solution {
public:
    vector<int> partitionLabels(string s) {
        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(i == right){
                result.push_back(right-left+1);
                left = i + 1;
            }
        }
        return result;
    }
};时间复杂度:O(n)
空间复杂度:O(1)
三、56. 合并区间
题目链接/文章讲解/视频讲解:https://programmercarl.com/0056.%E5%90%88%E5%B9%B6%E5%8C%BA%E9%97%B4.html
状态:已解决
1.思路
我想的比较直接,这道题很明显还是一个找重叠区间的题,只不过前面的题都是计算去掉重叠区间后未重叠区间的数量,或者是,数轴上分开的区间的数量;而此题是要求你找到重叠区间后做合并操作。怎么合并?我的想法是延申上题的做法,用一个变量来记录每次重叠的左边界,然后找到重叠的区间(intervals[i][0] <= intervals[i-1][1]),就合并区间(具体操作是取intervals[i][1] 和intervals[i-1][1]中的最大值,即更新区间右边界)。
2.代码实现
class Solution {
public:
    static bool cmp(const vector<int>& v1, const vector<int>& v2){
    //第一元素相等时,再比较第二元素
        if (v1[0] == v2[0])
            return v1[1] < v2[1];
        return v1[0] <= v2[0];
    }
    vector<vector<int>> merge(vector<vector<int>>& intervals) {
        if(intervals.size()==1) return intervals;
        sort(intervals.begin(),intervals.end(),cmp);
        int left = intervals[0][0];
        vector<vector<int>> result;
        for(int i=1;i<intervals.size();i++){
            if(intervals[i][0]>intervals[i-1][1]){//与前面区间不重叠
                result.push_back({left,intervals[i-1][1]});//将前面的重叠区间存入结果数组
                left = intervals[i][0];//更新新的重叠区间的左边界
            }
            else{
                intervals[i][1] = max(intervals[i][1],intervals[i-1][1]);//合并重叠区间,也就是更新右边界
            }
        }
        result.push_back({left,max(intervals[intervals.size()-1][1],intervals[intervals.size()-2][1])});//最后一个区间是根据右边界是否在前面重叠区间中来考虑的。
        return result;
    }
};时间复杂度: O(nlogn)
空间复杂度: O(logn),排序需要的空间开销



















