class Solution
{
private:
static bool cmp(const vector<int> &a,const vector<int> &b){
if(a[0]==b[0]) return a[1]<b[1];
return a[0]<b[0];
}
public:
int eraseOverlapIntervals(vector<vector<int>> &intervals)
{
if(intervals.size()==0) return 0;
sort(intervals.begin(),intervals.end(),cmp);
int nums=0;
vector<vector<int>> last;
last.push_back(intervals[0]);
for(int i=1;i<intervals.size();i++){
if(last[0][1]>intervals[i][0]){
nums++;
last[0]=last[0][1]>intervals[i][1]?intervals[i]:last[0];
}else{
last[0]=intervals[i];
}
}
return nums;
}
};
和昨天的社保气球很像,按照那个思路写了一下,发现还是有些案例不能通过。
最后发现是想的太简单了,没有考虑到后面的区间包含的范围比前面的区间小的情况,从而不能找出最小区间,导致不能找到最小删除次数。
题目链接:763. 划分字母区间 - 力扣(LeetCode)
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;
}
};
用一个数组来表示出现过字符的最远位置。
当右边界right==最远位置就可以把他放进答案里面了。
class Solution {
public:
vector<vector<int>> merge(vector<vector<int>>& intervals) {
vector<vector<int>> result;
if (intervals.size() == 0) return result; // 区间集合为空直接返回
// 排序的参数使用了lambda表达式
sort(intervals.begin(), intervals.end(), [](const vector<int>& a, const vector<int>& b){return a[0] < b[0];});
// 第一个区间就可以放进结果集里,后面如果重叠,在result上直接合并
result.push_back(intervals[0]);
for (int i = 1; i < intervals.size(); i++) {
if (result.back()[1] >= intervals[i][0]) { // 发现重叠区间
// 合并区间,只更新右边界就好,因为result.back()的左边界一定是最小值,因为我们按照左边界排序的
result.back()[1] = max(result.back()[1], intervals[i][1]);
} else {
result.push_back(intervals[i]); // 区间不重叠
}
}
return result;
}
};