AC代码:
class Solution {
public:
int findMinArrowShots(vector<vector<int>>& points) {
sort(points.begin(), points.end(),
[](vector<int> a, vector<int> b) { return a[0] < b[0]; });
int left = points[0][0];
int right = points[0][1];
int ans = 1;
for (int i = 1; i < points.size(); ++i) {
vector<int> point = points[i];
// 新的左边界要比原来的右边界还要大
if (point[0] > right) {
ans++;
left = point[0];
right = point[1];
}
// 更大的左边界
if (point[0] > left) {
left = point[0];
}
// 更小的右边界
if (point[1] < right) {
right = point[1];
}
}
return ans;
}
};
- 435. 无重叠区间
无重叠区间问题的贪心算法核心思想是:优先选择结束时间早的区间,这样可以为后面的区间留下更多的空间。
算法步骤:
- 按结束时间排序:将所有区间按照结束时间升序排列
- 贪心选择:遍历排序后的区间,每次选择结束时间最早且不与已选区间重叠的区间
- 计数:统计需要移除的区间数量 AC代码:
class Solution {
public:
int eraseOverlapIntervals(vector<vector<int>>& intervals) {
sort(intervals.begin(), intervals.end(),
[](vector<int> a, vector<int> b) { return a[1] < b[1]; });
int ans = 0;
int right = intervals[0][1];
for (int i = 1; i < intervals.size(); ++i) {
if (intervals[i][0] < right) {
ans++;
continue;
}
right = intervals[i][1];
}
return ans;
}
};
代码如下:
class Solution {
public:
vector<int> partitionLabels(string s) {
vector<vector<int>> positions;
unordered_map<char, int> s_map;
int i = 0;
// 获取每个字母出现的左右边界
for (int j = 0; j < s.size(); ++j) {
if (s_map.find(s[j]) == s_map.end()) {
s_map.emplace(s[j], i);
positions.push_back(vector<int>{j, j});
i++;
} else {
positions[s_map[s[j]]][1] = j;
}
}
int left = positions[0][0];
int right = positions[0][1];
vector<int> ans;
for (int j = 1; j < positions.size(); ++j) {
// 如果当前右边界小于当前查看位置的左边界,则可以在此划分
if (positions[j][0] > right) {
ans.push_back(right - left + 1);
left = positions[j][0];
right = positions[j][1];
} else {
// 否则,当前位置的字符也要归为同一划分中
// 此时,如果当前位置的右边界大于right,则右边界要向右延伸
if (positions[j][1] > right) {
right = positions[j][1];
}
}
}
ans.push_back(right - left + 1);
return ans;
}
};
// 可以只记录字母最远的出现位置,然后从前往后遍历S
// 维护right为前面所有字符的最后出现的位置的最大值
// 当i等于right时,就表示前面出现的字母最远就到这个边界了,这里就是分割点
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;
}
};