碎碎念:加油
参考:代码随想录
452. 用最少数量的箭引爆气球
题目链接
思想
局部最优: 让重叠的气球尽量在一起,用一支弓箭射。
全局最优: 用最少数量的箭引爆气球。
首先对气球进行排序,可以按照左边界排序,这样可能会重叠的气球排在一起。
如何判断气球重叠 ,因为左边界已经排序了,所以判断看右边界即可。如果第i个气球的左边界小于等于前一个气球的右边界,说明两个气球重叠了。
此时我们想看这两个气球和下一个气球是否重叠 ,就需要更新右边界,更新为两个气球右边界的最小值。更新右边界,用来和下一个气球比较。
题解
// cpp
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][0], points[i - 1][0]);
}
}
return result;
}
};
# python
class Solution:
def findMinArrowShots(self, points: List[List[int]]) -> int:
if len(points) == 0:
return 0
points.sort(key=lambda x:x[0])
result = 1
for i in range(1, len(points)):
if points[i][0] > points[i - 1][1]:
result += 1
else:
points[i][1] = min(points[i][1], points[i - 1][1])
return result
反思
result从1开始,因为显然使得所有气球都爆炸的箭的数量最少为1。
435. 无重叠区间
题目链接
思想
本题的思想和上一题很相似。
首先排序,让相邻的区间尽可能挨在一起。本做法用的是按照左边界排序。
判断相邻区间是否重叠: 如果当前遍历到的区间的左边界小于上一个区间的右边界,那么它们就是重叠的,result加一,更新右边界的大小,更新为两个区间右边界中较小的那个。
题解
// cpp
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 result = 0;
for (int i = 1; i < intervals.size(); i++) {
if (intervals[i][0] < intervals[i - 1][1]) {
result++;
intervals[i][1] = min(intervals[i][1], intervals[i - 1][1]);
}
}
return result;
}
};
# python
class Solution:
def eraseOverlapIntervals(self, intervals: List[List[int]]) -> int:
if len(intervals) == 0:
return 0
intervals.sort(key=lambda x:x[0])
result = 0
for i in range(1, len(intervals)):
if intervals[i][0] < intervals[i - 1][1]:
result += 1
intervals[i][1] = min(intervals[i][1], intervals[i - 1][1])
return result
反思
763.划分字母区间
题目链接
思想
遍历字符串,统计每个字符出现的最远位置。
遍历字符串,更新字符的最远出现下标,如果找到字符的最远出现位置下标和当前的下标相等了,就找到了分割点。
题解
// cpp
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;
}
};
# python
class Solution:
def partitionLabels(self, s: str) -> List[int]:
hash_ = {}
for i, ch in enumerate(s):
hash_[ch] = i
result = []
left = 0
right = 0
for i, ch in enumerate(s):
right = max(right, hash_[ch])
if i == right:
result.append(right - left + 1)
left = i + 1
return result