435. 无重叠区间
思路
和 452. 用最少数量的箭引爆气球 一样的思路
为贪心算法的区间问题。
解题方法
- 排序
- 遍历,重合的话取最小的右边界作为截取点
复杂度
- 时间复杂度:
添加时间复杂度, 示例: O ( n l o g n ) O(nlogn) O(nlogn)
- 空间复杂度:
添加空间复杂度, 示例: O ( n ) O(n) O(n)
Code
class Solution {
public int eraseOverlapIntervals(int[][] intervals) {
// 排序,左边界升序,二重右边界升序,注意,不排右边界也一样
Arrays.sort(intervals, (a, b) -> {
int c = Integer.compare(a[0], b[0]);
if (c == 0) {
return Integer.compare(a[1], b[1]);
}
return c;
});
int result = 0;
// 取第一个位置的右边界为截取点
int pre = intervals[0][1];
// 相交的时候取最小的右边
for(int i = 1; i < intervals.length; i++) {
if (intervals[i][0] < pre) {
result++;
pre = Math.min(pre, intervals[i][1]);
} else {
pre = intervals[i][1];
}
}
return result;
}
}
763. 划分字母区间
思路
讲述看到这一题的思路
解题方法
- 记录 s 中各个字母的最远位置
- 持续更新最远位置,直到最远位置等于i,开启下一段区间
复杂度
-
时间复杂度: O ( n ) O(n) O(n)
-
空间复杂度: O ( 1 ) O(1) O(1)
Code
class Solution {
public List<Integer> partitionLabels(String s) {
List<Integer> result = new ArrayList<>();
// 记录 s 中各个字母的最远位置
int[] farPos = new int[26];
for (int i = 0; i < s.length(); i++) {
farPos[s.charAt(i) - 'a'] = i;
}
// 持续更新最远位置,直到最远位置等于i,开启下一段区间
int start = 0;
int end = 0;
for (int i = 0; i < s.length(); i++) {
end = Math.max(farPos[s.charAt(i) - 'a'], end);
if (i == end) {
result.add(end - start + 1);
start = end + 1;
}
}
return result;
}
}
56. 合并区间
思路
讲述看到这一题的思路
解题方法
- 排序
- 遍历,判断边界条件
复杂度
- 时间复杂度:
添加时间复杂度, 示例: O ( n ) O(n) O(n)
- 空间复杂度:
添加空间复杂度, 示例: O ( n ) O(n) O(n)
Code
class Solution {
// 1. 排序
// 2. 遍历,判断边界条件
public int[][] merge(int[][] intervals) {
Arrays.sort(intervals, (a, b) -> a[0] - b[0]);
List<int[]> result = new LinkedList<>();
// 合并区间边界,初始化
int start = intervals[0][0];
int end = intervals[0][1];
for (int i = 1; i < intervals.length; i++) {
// 当前区间左边界和上一个合并区间右边界重叠,更新重叠区间右边界
if (end >= intervals[i][0]) {
end = Math.max(end, intervals[i][1]);
} else {
result.add(new int[]{start, end});
// 更新下一个重叠区间
start = intervals[i][0];
end = intervals[i][1];
}
}
// 收尾处理
result.add(new int[]{start, end});
return result.toArray(new int[result.size()][]);
}
}