435. 无重叠区间
class Solution {
public:
static bool cmp(const vector<int>& a, const vector<int>& b){
return a[0]<b[0];
}
int eraseOverlapIntervals(vector<vector<int>>& intervals) {
sort(intervals.begin(), intervals.end(), cmp);
int result=0;
for (int i=1; i<intervals.size(); i++){
if (intervals[i][0] < intervals[i-1][1]){ //发生重叠
result++;
intervals[i][1]= min(intervals[i][1], intervals[i-1][1]);
}
}
return result;
}
};
这道题比想象中更巧妙,我觉得和上一道题射气球其实不一样。
射气球维护的是一个重叠区间范围,所以每次都将上一个区间的右边界维护为最小的那个,保证这个区间内的元素都是重叠的,如果超过了上一个最大右边界的右区间就说明当前元素和上一个最大区间不能合并,必须增加一支箭。
对于本题,我觉得维护最大重叠区域范围的思路并不好想,看了评论区才明白,intervals[i][1]= min(intervals[i][1], intervals[i-1][1]);删除的优先级是1、当前区间和上一个区间中最大的那一个,2、当前区间。
为什么是这样?
因为我们首先对所有区间根据左起始点进行了排序,之后发生重叠时,将当前元素的右区间更新为当前区域右端点和上一个元素右端点的最大值。如果当前右端点比上一个右端点要靠左,说明上一个区间肯定比当前区间长,因为已经排序了,上一个区间的左端点已经更小了,并且其右端点更大,说明上一个区间比较长。因为题干要求是删除最少的区间数量,那我们肯定优先删除长的那个。所以将当前区间保留。
763.划分字母区间
class Solution {
public:
vector<int> partitionLabels(string s) {
vector<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 (right==i) //到达当前区间中最远元素,说明当前区间内的元素都在这个left right这个范围内了
{
result.push_back(right-left+1);
left = i+1;
}
}
return result;
}
};
理解题干比写代码难。
56. 合并区间
class Solution {
public:
static bool cmp(vector<int> a, vector<int> b){
return a[0]<b[0];
}
vector<vector<int>> merge(vector<vector<int>>& intervals) {
sort(intervals.begin(), intervals.end(), cmp);
vector<vector<int>> result;
result.push_back(intervals[0]);
for (int i=1; i<intervals.size(); i++){
if (intervals[i][0]<=result.back()[1]){
result.back()[1] = max(result.back()[1], intervals[i][1]); //更新右端点
}
else{ //保存独立区间
result.push_back(intervals[i]);
}
}
return result;
}
};
直接更新result中的内容还是第一次见。