代码随想录刷题Day36 | 435.无重叠区间、763.划分字母区间、56.合并区间

今日任务

435.无重叠区间

763.划分字母区间

56.合并区间

435.无重叠区间

方法一、贪心

主要思路

  • 先按照右边界排序
  • 然后用最小的右边界作为第一个判断有无重叠的界限 right
  • 遍历每个区间,当区间左边界小于 right 时,将不重叠区间数count加1,同时由于已经排好序,所以该区间的右边界在剩余所有区间里最小,将其右边界更新为 right 即可
  • 最后返回 区间总数 - 移除后不重叠区间数 n - count 即为需要移除的区间数
class Solution {
    static bool cmp(const vector<int> &in1, const vector<int> &in2) {
        return in1[1] < in2[1];
    }

public:
    int eraseOverlapIntervals(vector<vector<int>>& intervals) {
        int n = intervals.size();
        if (n < 2) return 0;
        sort(intervals.begin(), intervals.end(), cmp);
        int right = intervals[0][1], count = 1; // count表示不重叠区间数
        for (int i = 1; i < n; ++i) {
            if (intervals[i][0] >= right) {
                right = intervals[i][1];
                count++;
            }
        }
        return n - count;
    }
};

763.划分字母区间

方法一:贪心

主要思路

  • 先遍历一次字符串,求出每个字母最后出现的下表,记录到哈希表中

  • 然后再遍历字符串,每次更新本次划分的子串的右边界下标 ed,同时将长度len加一

    • ed 计算方式是:

      当前子串中前面已经出现的所有字符串最靠右出现的下标ed = max(hash[s[i] - '0'], ed)

    • 如果当前字符串的下标i 与 当前划分子串最右边界 ed 相等,那么该子串划分完毕,将本子串长度放入答案,然后将len重置为0

class Solution {
public:
    vector<int> partitionLabels(string s) {
        int n = s.size();
        if (n < 2) return vector<int>{1};
        int hash[27] = {0};
        vector<int> res;
        for (int i = 0; i < n; ++i) {
            hash[s[i] - 'a'] = i;
        }
        int len = 0, ed = 0;
        for (int i = 0; i < n; ++i) {
            ed = max(ed, hash[s[i] - 'a']);
            len++;
            if (ed == i) {
                res.push_back(len);
                len = 0;
            }
        }
        return res;
    }
};

56.合并区间

主要思路

  • 先根据区间左边界从小到大排序每个区间

  • 设置第一个区间的左边界为第一个合并区间的左边界st,右边界为合并区间的右边界ed

  • 后面遍历每个区间,当该区间与前一个区间有重叠时(internal[i][0] <= ed 就将 ed 更新为所有合并区间的右边界的最大值 ed = max(internal[i][1], ed)

  • 当没有重叠时,就将上一次合并的区间放入结果 res.push_back({st, ed}),并更新 st和ed作为下一个合并区间的左右边界

class Solution {
    static bool cmp(const vector<int> &u, const vector<int> &v) {
        return u[0] < v[0];
    }
public:
    vector<vector<int>> merge(vector<vector<int>>& intervals) {
        int n = intervals.size();
        if (n < 2) return intervals;
        sort(intervals.begin(), intervals.end(), cmp);
        vector<vector<int>> res;
        int st = intervals[0][0], ed = intervals[0][1];
        for (int i = 1; i < n; ++i) {
            if (intervals[i][0] <= ed) {
                ed = max(ed, intervals[i][1]);
            } else {
                res.push_back({st, ed});
                st = intervals[i][0];
                ed = intervals[i][1];
            }
        }
        res.push_back({st, ed}); // 最后一次在循环内肯定没被放入res,将其放入循环外减少判断次数
        return res;
    }
};

你可能感兴趣的:(算法,贪心算法)