Day36 | 435. 无重叠区间, 763.划分字母区间, 56. 合并区间

Day36 | 435. 无重叠区间, 763.划分字母区间, 56. 合并区间

无重叠区间

LeetCode题目:https://leetcode.cn/problems/non-overlapping-intervals/

整体思路

  区间覆盖问题,可以注意到的是,求的是最小要删去的区间个数。因此可以得知,如果以左区间从小到大进行排列,要求的最少删去区间,每次应该删去右边界较大的区间。这样可以保证每次删除都是最有可能有多个重叠的部分。

  即代码的体现就是每次出现重叠部分,便将当前的边界更新为两个重叠区间中最小的右边界。此时也可以看做删除了一个区间,所以nums++。

class Solution {
public:
    static bool compare(const vector<int>& a,const vector<int>& b){
        if(a[0]<b[0]){
            return true;
        }else if(a[0]==b[0]){
            return a[1]<b[1];
        }
        return false;
    }
    int eraseOverlapIntervals(vector<vector<int>>& intervals)  {
        sort(intervals.begin(),intervals.end(),compare);
        int nums=0;
        for(int i=1;i<intervals.size();i++){
            if(intervals[i-1][1]>intervals[i][0]){
                intervals[i][1] = min(intervals[i-1][1],intervals[i][1]);
                nums++;
                continue;
            }
        }
        return nums;
    }
};

划分字母区间

LeetCode题目:https://leetcode.cn/problems/partition-labels/

解题思路

  此部分也是重叠区间的问题,只不过是要识别重叠部分的最大区间,即在右区间取得最大值后,定义左右区间为0并进行循环判断。如果右区间比当前字母的最远边界大,则说明右区间需要更新。如果右区间不变,则说明当期字母的位置在区间内部,满足字母区间的划分。

  直到迭代到与右区间相同的索引位置,说明之前的所有字母,没有区间范围超过该右区间的,因此将其right-left压入vector数组,并更新left为right+1。

  代码如下:

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;
    }
};

合并区间

LeetCode题目:https://leetcode.cn/problems/merge-intervals/

解题思路

  合并区间其实就是求得最大的独立区间,因此只需要将重叠时找最小右边界改为最大右边界。然后进行查找即可。

  直接代码如下:

class Solution {
public:
    static bool cmp(const vector<int>& a,const vector<int>& b){
        if(a[0]<b[0]){
            return true;
        }else if(a[0]==b[0]){
            return a[1]<b[1];
        }
        return false;
    }
    vector<vector<int>> merge(vector<vector<int>>& intervals) {
        vector<vector<int>> result;
        sort(intervals.begin(),intervals.end(),cmp);
        int startIndex = intervals[0][0];
        for(int i=1;i<intervals.size();i++){
            if(intervals[i-1][1]>=intervals[i][0]){
                intervals[i][1] = max(intervals[i-1][1],intervals[i][1]);
                continue;
            }
            result.push_back(vector<int>{startIndex,intervals[i-1][1]});
            startIndex = intervals[i][0];
        }
        result.push_back(vector<int>{startIndex,intervals[intervals.size()-1][1]});
        return result;
    }
};

  同时,因为经过排序,左边界一定是有序排列,那么可以直接将最小的第一个区间存入result,然后对右边界进行更新。如果右边界和下一个区间有重叠就重复进行更新。知道无重叠后,再压入当前的最小区间(即当前区间),然后重复操作即可。

  直接代码如下:

class Solution {
public:
    static bool cmp(const vector<int>& a,const vector<int>& b){
        if(a[0]<b[0]){
            return true;
        }else if(a[0]==b[0]){
            return a[1]<b[1];
        }
        return false;
    }
    vector<vector<int>> merge(vector<vector<int>>& intervals) {
        vector<vector<int>> result;
        sort(intervals.begin(),intervals.end(),cmp);
        result.push_back(intervals[0]);
        for(int i=1;i<intervals.size();i++){
            if(result.back()[1]>=intervals[i][0]){
                result.back()[1] = max(result.back()[1],intervals[i][1]);
            }else{
                result.push_back(intervals[i]);
            }
        }
        return result;
    }
};

你可能感兴趣的:(数据结构,算法,数据结构,leetcode)