452. 用最少数量的箭引爆气球
1.按气球的左侧排序
2.维护一个start,end区间,若下一个气球在之前气球范围外就需要多加一个飞镖,反之,不需要,end维护为两者重叠部分,即更小的end。
cpp
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];
}
int findMinArrowShots(vector<vector<int>>& points) {
sort(points.begin(), points.end());
int start = points[0][0];
int end = points[0][1];
int count = 1;
for(int i = 1; i < points.size(); i++){
if(points[i][0] <= end){
end = min(points[i][1], end);
}
else{
start = points[i][0];
end = points[i][1];
count++;
}
}
return count;
}
435. 无重叠区间
排序:先按区间左端点升序(左端点相同则按右端点升序),让区间按 "从左到右" 的顺序排列;
遍历判断 :维护当前不重叠区间的「最右端点」end,遍历后续区间:
-
若当前区间和
end重叠 → 需要删除(计数 + 1),且更新end为「更小的右端点」(保留更短的区间,减少后续重叠); -
若不重叠 → 更新
end为当前区间的右端点(当前区间成为新的 "不重叠基准");
cpp
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];
}
int eraseOverlapIntervals(vector<vector<int>>& intervals) {
sort(intervals.begin(), intervals.end(), cmp);
int count = 0;
int end = intervals[0][1];
for(int i = 1; i < intervals.size(); i++){
if(intervals[i][0] < end){
count++;
end = min(intervals[i][1], end);//选择跨度尽可能小的
}
else {
end = intervals[i][1];
}
}
return count;
}
763. 划分字母区间
预处理(记录最后位置) :遍历字符串,记录每个字符在字符串中最后一次出现的下标 (比如字符 'a' 最后出现在下标 8,就记pos['a'-'a']=8);
贪心划分区间 :遍历字符串,维护当前区间的「起始位置start」和「最远边界end」:
-
遍历过程中,不断扩展
end为 "当前字符最后出现位置" 和 "当前end" 的最大值(保证区间内所有字符的最后位置都在区间内); -
当遍历到
end时,说明当前区间的所有字符都不会超出这个边界 → 完成一次划分,记录长度,重置start和end; -
遍历结束后,处理最后一个区间。
cpp
vector<int> partitionLabels(string s) {
int pos[26] = {0};
for(int i = 0; i < s.length(); i++){
pos[s[i] - 'a'] = i;
}
vector<int> res;
int start = 0;
int end = pos[s[0] - 'a'];
int len = 0;
for(int i = 0; i < s.length(); i++){
if(i <= end){
end = max(pos[s[i] - 'a'], end);
}
else{
len = end - start + 1;
res.push_back(len);
start = i;
end = pos[s[i] - 'a'];
}
}
len = end - start + 1;
res.push_back(len);
return res;
}