452. 用最少数量的箭引爆气球
题目链接:452. 用最少数量的箭引爆气球
文档讲解:代码随想录
状态:没想出来
思路:对气球终点位置排序,从第一个气球终点位置射出箭,看这支箭可以尽可能穿过几个气球,如果遇到一个气球的起点在当前箭的终点之后,说明当前这支箭不能再穿过这个气球了,需要再射出一支新的箭,并将新的箭的终点设为当前气球的终点。
题解:
// 按照气球的结束位置进行排序
Arrays.sort(points, Comparator.comparingInt(a -> a[1]));
// 初始化箭的数量为1,因为至少需要一支箭
int arrNum = 1;
// 初始化第一支箭的位置为第一个气球的结束位置
int end = points[0][1];
// 遍历所有气球
for (int[] point : points) {
// 如果当前气球的开始位置大于箭的结束位置,说明需要新的箭
if (point[0] > end) {
arrNum++; // 增加箭的数量
end = point[1]; // 更新箭的位置为当前气球的结束位置
}
}
// 返回所需的箭的数量
return arrNum;
435. 无重叠区间
题目链接:435. 无重叠区间
文档讲解:代码随想录
状态:还行
思路:先固定一边排序,然后考虑上个区间终点和当前区间的起点关系。
题解:
//起点排序
public int eraseOverlapIntervals1(int[][] intervals) {
// 按照区间的起始位置进行排序
Arrays.sort(intervals, Comparator.comparingInt(a -> a[0]));
// 记录需要移除的重叠区间数量
int remove = 0;
// 记录当前处理的区间的结束位置
int pre = intervals[0][1];
// 从第二个区间开始遍历
for (int i = 1; i < intervals.length; i++) {
// 如果当前区间的起始位置小于前一个区间的结束位置,
// 表示当前区间与前一个区间重叠
if (pre > intervals[i][0]) {
// 需要移除当前区间
remove++;
// 更新当前处理的区间的结束位置为当前区间结束位置和前一个区间结束位置的较小值
pre = Math.min(pre, intervals[i][1]);
} else {
// 如果当前区间与前一个区间不重叠,更新当前处理的区间的结束位置为当前区间的结束位置
pre = intervals[i][1];
}
}
// 返回需要移除的重叠区间数量
return remove;
}
//终点排序,(推荐)
public int eraseOverlapIntervals(int[][] intervals) {
// 根据区间的终点进行排序
Arrays.sort(intervals, (a, b) -> Integer.compare(a[1], b[1]));
int res = -1; // 初始化结果为 -1,因为第一个区间即使重叠也不算在移除计数中
int end = intervals[0][1]; // 初始化end为第一个区间的终点
// 遍历所有区间
for (int[] interval : intervals) {
if (interval[0] < end) { // 当前区间与前一个区间重叠
res++; // 增加移除重叠区间的计数
} else { // 当前区间不重叠
end = interval[1]; // 更新end为当前区间的终点
// end = Math.min(end, interval[1]); //因为是对终点进行排序的interval[1]肯定大于或等于 end,所以不需要这个,如果是对起点排序则不能少
}
}
return res; // 返回移除重叠区间的数量
}
类似重叠区间问题解题模板:
- 排序:根据问题需求,通常推荐对区间的终点进行排序。
- 考虑上个区间的终点和当前区间的起点的关系:这是判断区间是否重叠的关键。
- 根据题意求解:根据具体问题的要求来计算结果,例如计算需要移除的区间数量,找到最多数量的无重叠区间等。
763.划分字母区间
题目链接:763.划分字母区间
文档讲解:代码随想录
状态:把问题想复杂了,写了一个划分片段最少的版本出来了。。。。
思路:
- 统计每一个字符最后出现的位置。
- 从头遍历字符,并更新字符的最远出现下标,如果找到字符最远出现位置下标和当前下标相等了,则找到了分割点。
题解:
public List<Integer> partitionLabels(String s) {
List<Integer> res = new ArrayList<>(); // 结果列表,用于存放每个片段的长度
char[] chars = s.toCharArray(); // 将输入的字符串转换为字符数组,便于处理
int[] counter = new int[26]; // 记录每个字符最后出现的位置
for (int i = 0; i < chars.length; i++) {
counter[chars[i] - 'a'] = i; // 更新字符对应的最后出现位置
}
int far = -1; // 当前片段的最远位置
int start = 0; // 当前片段的起始位置
for (int i = 0; i < chars.length; i++) {
far = Math.max(far, counter[chars[i] - 'a']); // 更新当前片段的最远位置
if (i == far) { // 如果当前位置是当前片段的结束位置
res.add(i - start + 1); // 将当前片段的长度添加到结果列表中
start = i + 1; // 更新下一个片段的起始位置
}
}
return res; // 返回结果列表
}