算法训练营day36_贪心算法(3.8)
435.无重叠区间
额,没咋想,试试就A了;
先按照右端点排序;
看一下last可以穿几个区间,答案就加几,当l>=last时更新last;
由于是排过序,前面的区间就算跟当前区间有重叠,也不会额外计算,它只会看后面的区间;
class Solution {
public:
static int cmp(vector<int>& t1,vector<int>& t2){
return t1[1]<t2[1];
}
int eraseOverlapIntervals(vector<vector<int>>& intervals) {
sort(intervals.begin(),intervals.end(),cmp);
int ans=0,last=-1e5;
for(int i=0;i<intervals.size();i++){
int l=intervals[i][0],r=intervals[i][1];
if(last==-1e5||l>=last){
last=r;
}
else ans++;
}
return ans;
}
};
763.划分字母区间
同一个字母只能出现在一个片段,先找到每个位置字母的最后出现位置pos,该字母到pos一定得是一个片段;
从左往后遍历,r为i的pos,内置一个指针j遍历i到r,如果有某位置的pos大于r,更新r;
由于要尽可能的多划分片段,如果有某个位置字母就只有自己,单独划分一个片段;
class Solution {
public:
vector<int> partitionLabels(string s) {
int n=s.size();
vector<int> pos(n+1,0);
vector<int> ans;
s=" "+s;
for(int i=1;i<=n;i++){
char x=s[i];
for(int j=n;j>=i;j--){
if(s[j]==x){
pos[i]=j;
break;
}
}
}
int last=0;
for(int i=1;i<=n;i++){
if(pos[i]==i){
ans.push_back(1);
continue;
}
int r=pos[i];
int j;
for(j=i;j<=r;j++){
r=max(r,pos[j]);
}
last+=r-i+1;
ans.push_back(last);
last=0;
i=j-1;
}
return ans;
}
};
56.合并区间
没啥好说的;
设置a,b作为一个临时区间用来合并;
a,b初始化为-1作为哨兵,l>a就先放ans再更新a,b;
关键是最后还要再放一次a,b到ans(这里数组明确说了不为空,就不加if了);
class Solution {
public:
vector<vector<int>> merge(vector<vector<int>>& intervals) {
vector<vector<int>> ans;
sort(intervals.begin(),intervals.end());
int a=-1,b=-1;
for(int i=0;i<intervals.size();i++){
int l=intervals[i][0],r=intervals[i][1];
if(a==-1||l>b){
if(a!=-1) ans.push_back({a,b});
a=l;
b=r;
}
b=max(b,r);
}
ans.push_back({a,b});
return ans;
}
};