文章链接:452. 用最少数量的箭引爆气球、435. 无重叠区间、763.划分字母区间
452.用最少数量的箭引爆气球
思路:
1.用 左边界 将全部数组从小到大排;
2.更新覆盖范围的 最大左边界 和 最小右边界 ;
3.若遍历到的气球的左边界大于 最小右边界 ,那么需要增加一支箭;
class Solution {
public:
static bool cmp(const vector<int>& a, const vector<int>& b) {
// 用左边界从小到大排
return a[0] < b[0];
}
int findMinArrowShots(vector<vector<int>>& points) {
if (points.size() == 0) return 0;
sort(points.begin(), points.end(), cmp);
int result = 1;
for (int i = 1; i < points.size(); i++) {
if (points[i][0] > points[i - 1][1]) {
result++; // 需要增加一支箭
} else {
// 更新重叠的最小右边界
points[i][1] = min(points[i - 1][1], points[i][1]);
}
}
return result;
}
};
435.无重叠区间
思路:
1.将区间根据左边界排序;
2.统计重叠区间数;
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) {
if (intervals.size() == 0) return 0;
sort(intervals.begin(), intervals.end(), cmp); // 用左边界排序
int count = 0; // 统计重叠区间的个数
for (int i = 1; i < intervals.size(); i++) {
if(intervals[i][0] < intervals[i - 1][1]) { // 重叠
count++;
intervals[i][1] = min(intervals[i - 1][1], intervals[i][1]);
// 更新重叠区间的最小右边界
}
}
return count;
}
};
763.划分字母区间
思路:
1.用一个数组记录每个字符的最远出现下标;
2.寻找分割点,若遍历到 i == 符合结果的字符串的最远右边界 ,则为分割点。
class Solution {
public:
vector<int> partitionLabels(string s) {
int hash[27] = {0};
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;
}
};