435. 无重叠区间
给定一个区间的集合 intervals ,其中 intervals[i] = [starti, endi] 。返回 需要移除区间的最小数量,使剩余区间互不重叠 。
示例 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 解释: 你不需要移除任何区间,因为它们已经是无重叠的了。
思路
- 排序:按照每个区间的开始时间对所有区间进行排序。
- 初始化:初始化两个变量:一个是
count,用于记录需要移除的区间数量,初始化为 0;另一个是end,用于记录当前不重叠区间集合中最后一个区间的结束时间,初始化为第一个区间的结束时间。 - 遍历:接着,我们从第二个区间开始,遍历所有排序后的区间。
- 如果当前区间与前一个区间重叠(即,当前区间的开始时间小于
end),则增加count,并更新end为当前区间和前一个区间中结束时间较早的那一个(为了给后续区间留下更多空间)。 - 如果当前区间不与前一个区间重叠,更新
end为当前区间的结束时间。
- 结果:最后,
count将是需要移除的区间的最小数量。
题解
class Solution {
public:
int eraseOverlapIntervals(vector<vector<int>>& intervals) {
int count = 0;
if (intervals.empty() || intervals.size() == 1) {
return 0;
}
sort(intervals.begin(), intervals.end(), [](const vector<int>& a, const vector<int>& b) {
return a[0] < b[0];
});
int end = intervals[0][1];
for (int i = 1; i < intervals.size(); ++i) {
if (intervals[i][0] < end) {
count++;
end = min(end, intervals[i][1]);
} else {
end = intervals[i][1];
}
}
return count;
}
};
763. 划分字母区间
给你一个字符串 s 。我们要把这个字符串划分为尽可能多的片段,同一字母最多出现在一个片段中。 注意,划分结果需要满足:将所有划分结果按顺序连接,得到的字符串仍然是 s 。 返回一个表示每个字符串片段的长度的列表。
示例 1:输入:s = "ababcbacadefegdehijhklij" 输出:[9,7,8] 解释: 划分结果为 "ababcbaca"、"defegde"、"hijhklij" 。 每个字母最多出现在一个片段中。 像 "ababcbacadefegde", "hijhklij" 这样的划分是错误的,因为划分的片段数较少。 示例 2: 输入:s = "eccbbbbdec" 输出:[10]
思路
- 预处理:首先遍历整个字符串,用一个哈希表记录每个字符最后一次出现的位置。
- 初始化:设置两个变量
start和end,分别表示当前片段的起始和结束位置。初始都为0。 - 遍历与更新:遍历字符串,对每个字符,更新
end为当前片段所有字符最后出现位置的最大值,因为不断更新end,最后end=i的时候说明当前字符以及之前的所有字符都会在这个end的左边。 - 切割片段:每当遍历到的当前索引
i等于end时,切割出一个新的片段,长度为end - start + 1,并更新start为end + 1。 - 返回结果:返回所有片段的长度组成的列表。
题解
class Solution {
public:
vector<int> partitionLabels(string s) {
unordered_map<char,int> last_occurrence;
for(int i=0;i<s.size();i++){
last_occurrence[s[i]]=i;
}
int end=0,start=0;
vector<int> result;
for (int i = 0; i < s.size(); ++i) {
end = max(end, last_occurrence[s[i]]);
if (i == end) {
result.push_back(end - start + 1);
start = end + 1;
}
}
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] 可被视为重叠区间。
思路
- 排序:首先按照每个区间的起始时间对所有区间进行排序。
- 初始化:然后初始化一个空的结果数组
result。 - 遍历与合并:接着,遍历排序后的区间。
- 如果结果数组为空,或者当前区间与结果数组中最后一个区间没有重叠,直接将当前区间加入结果数组。
- 如果当前区间与结果数组中最后一个区间有重叠,合并这两个区间。
- 返回结果:最后,返回结果数组
result。
题解
class Solution {
public:
vector<vector<int>> merge(vector<vector<int>>& intervals) {
// 按照区间的起始时间进行排序
sort(intervals.begin(), intervals.end());
// 初始化结果数组
vector<vector<int>> result;
// 遍历所有区间
for (const auto& interval : intervals) {
// 如果结果数组为空,或者当前区间与结果数组中最后一个区间没有重叠,
// 直接将当前区间加入结果数组
if (result.empty() || result.back()[1] < interval[0]) {
result.push_back(interval);
} else {
// 否则,合并有重叠的区间
result.back()[1] = max(result.back()[1], interval[1]);
}
}
return result; // 返回结果数组
}
};