代码随想录算法训练营
Day30 代码随想录算法训练营第30 天 |LeetCode452. 用最少数量的箭引爆气球 LeetCode435. 无重叠区间 LeetCode763.划分字母区间
目录
前言
LeetCode452. 用最少数量的箭引爆气球
LeetCode435. 无重叠区间
LeetCode763.划分字母区间
一、LeetCode452. 用最少数量的箭引爆气球
1.题目链接
2.思路
(1)贪心思路
局部最优:重叠部分尽可能在一起
全局最优:使用最少的箭射击
(2)表示重叠
1)按照起始位置从小到大排序
2)有重叠:前一个气球/前一组重叠气球的右侧边界大于等于后一个气球的左边界
points[i][0] <= points[i - 1][1]
注意:这里的重叠指的是后面气球和前面的重叠组合的公共部分产生重叠
3)没有重叠:前一个气球/前一组重叠气球的右侧边界小于后一个气球的左边界
points[i][0] > points[i - 1][1]
(3)如何记录箭数
从后向前,每次遍历气球i,会有两种情况
1)气球i没有和前一个重叠组合产生公共的重叠:箭数+1
因为当前的气球i要么完全不和其他气球重合,要么作为后序重叠组合的第一个气球,都要在这个气球上射箭
2)气球和前一个重叠组合产生公共重叠:箭数不变
- 因为重叠组合的箭数算在重叠组合的第一个气球上
- 但是需要更新重叠组合的公共重叠区域的右边界----取i的右边界和重叠区域右边界的最小值
(4)被射中的气球无序额外处理,因为我们每遍历一个气球都会解决这个气球对于箭数的影响,如果一个气球被射爆了,那么i向后移动,就等于不再考虑前面那个射爆的气球
3.题解
lass Solution {
public:
static bool cmp(vector<int> a, vector<int> b) { return a[0] < b[0]; }
int findMinArrowShots(vector<vector<int>>& points) {
sort(points.begin(), points.end(), cmp);
int res = 1;
for (int i = 1; i < points.size(); i++) {
if (points[i][0] > points[i - 1][1])
res++;
else {
points[i][1] = min(points[i - 1][1], points[i][1]);
}
}
return res;
}
};
二、LeetCode435. 无重叠区间
1.题目链接
2.思路
(1)贪心思路:求重叠区间个数
(2)重叠区间判断
- 注意,这里的重叠和上一题有所不同,这里认为[0,1][1,2]没有重叠区域
- 也就是说重叠判定是
intervals[i][0] < intervals[i - 1][1]
(3)在重叠是计数即可
3.题解
class Solution {
public:
static bool cmp(vector<int> a, vector<int> b) { return a[0] < b[0]; }
int eraseOverlapIntervals(vector<vector<int>>& intervals) {
int total = intervals.size();
int res = 0;
sort(intervals.begin(), intervals.end(), cmp);
for (int i = 1; i < total; i++) {
if (intervals[i][0] < intervals[i - 1][1]) {
intervals[i][1] = min(intervals[i - 1][1], intervals[i][1]);
res++;
}
}
return res;
}
};
三、LeetCode 763.划分字母区间
1.题目链接
2.思路
(1)思路
1)记录字符最远出现的下标
2)从前向后遍历,如果字符现在出现的下标是此前所有出现过的字符的最远出现的下标,则为分割点
far表示此前出现的所有元素的最远出现下标的最大值
(2)存放字符最远出现的下标:哈希
index[s[i]-'a']=i
(3)用start表示子字符串的起点,子字符串的长度是far-start+1
3.题解
class Solution {
public:
vector<int> partitionLabels(string s) {
vector<int> ans;
int n = s.size();
int index[26];
for (int i = 0; i < n; i++) {
index[s[i] - 'a'] = i;
}
int far = 0;
int start = 0;
for (int i = 0; i < n; i++) {
far = max(far, index[s[i] - 'a']);
if (far == i) {
ans.push_back(i - start + 1);
start = i + 1;
}
}
return ans;
}
};