一、435. 无重叠区间
主要思路:
- 依据左边界对所有区间排序
- 对区间进行遍历,如果当前区间的左边界大于等于 right值,则不会重叠,right值更新为当前区间的右边界。否则,进入下一步。
- 如果当前区间的右边界大于right值,则删除当前区间,并进入下一个循环(不需要更新right值)。否则,需要将前一个区间删除,同时将right值更新为当前区间的右边界。
以下是代码部分:
public class 无重叠区间435 {
//思路:先依据左点排序,
public int eraseOverlapIntervals(int[][] intervals) {
Arrays.sort(intervals, (a, b) -> Integer.compare(a[0], b[0]));
int right = intervals[0][1];
int res = 0;
for (int i = 1; i < intervals.length; i++) {
//如果当前的区间左端点小于上个区间右端点(有重合)
if( intervals[i][0] < right){
//有重合且当前区间右端点大于前一个区间,直接删除
if( intervals[i][1] > right){
res++;
//不需要更新right,直接下一轮
continue;
}else {
//小于前一个区间的右端点,则删除前一个区间
res++;
}
}
//更新right
right = intervals[i][1];
}
return res;
}
}
二、763.划分字母区间
主要思路:
- 首先记录每个字母出现的最大下标位置。
- 遍历一遍数组,将数组分为题目要求的一个个区间。max记录区间所有字母中最后出现的那个字母的下标。
- 在遍历的过程中更新max值,如果当前遍历的位置i 与max相等,则说明区间中的字母都找完了,之后不会再出现了。
- 重复第3步,直到遍历完所有元素。
以下是代码部分:
public class 划分字母区间763 {
//简化后的代码
public List<Integer> partitionLabels2(String s) {
int[] index = new int[26];
for (int i = 0; i < s.length(); i++) {
//更新每个字母的最右边下标
index[s.charAt(i) - 'a'] = i;
}
List<Integer> res = new ArrayList<>();
int tmp = 0;
//当前区间的最优边界
int max = 0;
for (int i = 0; i < s.length(); i++) {
//更新max在前边,有利于让第0个节点与其他节点统一处理
max = Math.max(max, index[s.charAt(i) - 'a']);
tmp++;
//判断是否到区间最优边界
if( i == max){
res.add(tmp);
tmp = 0;
}
}
return res;
}
}
三、56. 合并区间
这道题其实与第一道题很像,思路基本差不多。
主要思路:
- 依据左边界排序
- 遍历数组,分成一块块大区间,其中 tmp[0] 记录大区间的左边界,tmp[1] 记录大区间的右边界。
- 在遍历的过程中,tmp[0] 只在开启下一个大区间时更新,而 tmp[1] 则是取当前大区间的最大右边界。
- 如果当前小区间大于 tmp[1],说明合不到一块了,就开启下一个新的大区间。
- 最后,注意把最后一个大区间加入结果集中(for循环中没有记录最后一个)。
以下是代码部分:
public class 合并区间56 {
public int[][] merge(int[][] intervals) {
Arrays.sort(intervals, (a, b) -> a[0] - b[0]);
List<int[]> res = new ArrayList<>();
int[] tmp = new int[2];
tmp[0] = intervals[0][0];
int right = intervals[0][1];
for (int i = 1; i < intervals.length; i++) {
//如果当前的左边界大于上个局部区间的右边界,则分开
if( intervals[i][0] > right){
//更新右区间,收集结果
tmp[1] = right;
/*
//需要new一个对象加入到res
int[] p = new int[2];
p[0] = tmp[0];
p[1] = tmp[1];
res.add(p);
*/
res.add(new int[]{tmp[0], tmp[1]});
//更新新的左边界
tmp[0] = intervals[i][0];
}
//加入到前一个区间,更新right
right = Math.max(right, intervals[i][1]);
}
//由于都是在收集上个区间的结果,所以最后一个区间没有收集到。收集最后一个区间的结果
tmp[1] = right;
res.add(tmp);
//踩坑:超出时间限制。
return res.toArray(new int[res.size()][2]);
}
}