搜索
您的当前位置:首页LeetCode刷题day20——贪心

LeetCode刷题day20——贪心

来源:乌哈旅游

435. 无重叠区间

给定一个区间的集合 intervals ,其中 intervals[i] = [starti, endi] 。返回 需要移除区间的最小数量,使剩余区间互不重叠

注意 只在一点上接触的区间是 不重叠的。例如 [1, 2][2, 3] 是不重叠的。

示例 1:

输入: intervals = [[1,2],[2,3],[3,4],[1,3]]
输出: 1
解释: 移除 [1,3] 后,剩下的区间没有重叠。

示例 2:

输入: intervals = [ [1,2], [1,2], [1,2] ]
输出: 2
解释: 你需要移除两个 [1,2] 来使剩下的区间没有重叠。

示例 3:

输入: intervals = [ [1,2], [2,3] ]
输出: 0
解释: 你不需要移除任何区间,因为它们已经是无重叠的了。

提示:

  • 1 <= intervals.length <= 105
  • intervals[i].length == 2
  • -5 * 104 <= starti < endi <= 5 * 104
//easy,跟昨天的射气球一样的
class Solution {
public:
    int eraseOverlapIntervals(vector<vector<int>>& intervals) {
        // 这道题完全就是昨天写的射气球的变体,这里只需要求出非重叠区间的最大个数,就能得知需要移除的区间个数
        int sum = 0;
        sort(intervals.begin(), intervals.end(),
             [](vector<int>& a, vector<int>& b) { return a[1] < b[1]; });
        int line = INT_MIN;
        for (auto p : intervals) {
            if (p[0] >= line) {
                sum++;
                line = p[1];
            }
        }
        return intervals.size() - sum;
    }
};

763. 划分字母区间

给你一个字符串 s 。我们要把这个字符串划分为尽可能多的片段,同一字母最多出现在一个片段中。

注意,划分结果需要满足:将所有划分结果按顺序连接,得到的字符串仍然是 s

返回一个表示每个字符串片段的长度的列表。

示例 1:

输入:s = "ababcbacadefegdehijhklij"
输出:[9,7,8]
解释:
划分结果为 "ababcbaca"、"defegde"、"hijhklij" 。
每个字母最多出现在一个片段中。
像 "ababcbacadefegde", "hijhklij" 这样的划分是错误的,因为划分的片段数较少。 

示例 2:

输入:s = "eccbbbbdec"
输出:[10]

提示:

  • 1 <= s.length <= 500
  • s 仅由小写英文字母组成

分析:

构建字符的最后出现位置

  • 使用一个 index 数组来记录每个字符在字符串中最后一次出现的位置。也就是说,index[i] 存储的是字符 s[i]s 中的最后一个位置。
  • 对于每个字符 s[i],通过第二层循环从 i+1n-1 遍历,查找 s[i] 最后一次出现的索引,更新 index[i]

遍历并确定划分的点

  • 接下来,遍历字符串的每个字符,维护一个 Max 变量记录到当前位置为止的字符的最远位置,即 Max = max(Max, index[i])。这个 Max 表示当前字符及其之前的所有字符可以在 Max 的范围内完全包含。
  • 如果当前索引 iMax 相等,说明从 starti 这一段子串中的字符已经全部处理完,可以作为一个独立的子串,记录其长度并更新 starti
class Solution {
public:
    vector<int> partitionLabels(string s) {
        //统计每个字符出现的最后位置,然后从头开始遍历,寻找最大的范围,如果正遍历到最大范围,就是切割点
        vector<int> index(s.length(), 0);
        vector<int> result;
        for (int i = 0; i < s.length(); i++) {
            char c = s[i];
            int tmp = i;
            for (int j = i + 1; j < s.length(); j++) {
                if (c == s[j])
                    tmp = j;
            }
            index[i] = tmp;
        }
        int Max = -1;
        int start = -1;//这里注意,题目求的是长度
        for (int i = 0; i < s.length(); i++) {
            Max = max(Max, index[i]);
            if (Max == i) {
                result.push_back(i - start);
                start = i;
            }
        }
        return result;
    }
};

但是,时间复杂度是O(N^2),因为在确定字母出现的最后位置时,采用了两层循环。可以优化为O(N)。

class Solution {
public:
    vector<int> partitionLabels(string s) {
        // 记录每个字符最后出现的位置
        vector<int> lastIndex(26, -1); // 记录字符a到z的最后出现位置
        for (int i = 0; i < s.length(); i++) {
            lastIndex[s[i] - 'a'] = i;
        }
        
        vector<int> result;
        int start = 0, end = 0;
        
        for (int i = 0; i < s.length(); i++) {
            // 更新end为当前字符的最后出现位置
            end = max(end, lastIndex[s[i] - 'a']);
            
            // 如果当前索引i等于end,说明可以分割
            if (i == end) {
                result.push_back(i - start + 1);
                start = i + 1; // 更新start为下一个分割点的起始位置
            }
        }
        
        return result;
    }
};

56. 合并区间

以数组 intervals 表示若干个区间的集合,其中单个区间为 intervals[i] = [starti, endi] 。请你合并所有重叠的区间,并返回 一个不重叠的区间数组,该数组需恰好覆盖输入中的所有区间

示例 1:

输入:intervals = [[1,3],[2,6],[8,10],[15,18]]
输出:[[1,6],[8,10],[15,18]]
解释:区间 [1,3] 和 [2,6] 重叠, 将它们合并为 [1,6].

示例 2:

输入:intervals = [[1,4],[4,5]]
输出:[[1,5]]
解释:区间 [1,4] 和 [4,5] 可被视为重叠区间。

提示:

  • 1 <= intervals.length <= 104
  • intervals[i].length == 2
  • 0 <= starti <= endi <= 104

分析:

这题跟重叠区间,射气球差不多。关键在于判断重叠之后,要怎么处理。

class Solution {
public:
    vector<vector<int>> merge(vector<vector<int>>& intervals) {
        sort(intervals.begin(), intervals.end(),[](vector<int>& x,vector<int>& y) {
            return x[0]<y[0];
        });//按左边界排序
        vector<vector<int>> res;
        res.push_back(intervals[0]);
        for(int i=0;i<intervals.size();i++) {
            if(res.back()[1]>=intervals[i][0]) {//重叠,合并
                res.back()[1]=max(res.back()[1],intervals[i][1]);
            }
            else//不重叠
                res.push_back(intervals[i]);
        }
        return res;
    }
};

因篇幅问题不能全部显示,请点此查看更多更全内容

Top