代码随想录算法训练营day36 | 435. 无重叠区间,763.划分字母区间,56. 合并区间
- 435. 无重叠区间
- 763.划分字母区间
- 56. 合并区间
- 总结
435. 无重叠区间
教程视频:https://www.bilibili.com/video/BV1A14y1c7E1/?spm_id_from=333.788&vd_source=ddffd51aa532d23e6feac69924e20891
本题其实和上题452.用最少数量的箭引爆气球非常像,弓箭的数量就相当于是非交叉区间的数量。
本题求的则是交叉区间的数量,修改上题的边界条件和计数位置即可。
class Solution {
public int eraseOverlapIntervals(int[][] intervals) {
//按照左边界升序排列
Arrays.sort(intervals,(a,b)->Integer.compare(a[0],b[0]));
int count=0;
for(int i=1; i<intervals.length; i++){
if(intervals[i-1][1]<=intervals[i][0]){
continue;
}else{
//前两个有交叉
count++;
//删除长的区间
intervals[i][1]=Math.min(intervals[i-1][1],intervals[i][1]);
}
}
return count;
}
}
763.划分字母区间
教程视频:https://www.bilibili.com/video/BV18G4y1K7d5/?spm_id_from=pageDriver&vd_source=ddffd51aa532d23e6feac69924e20891
分为如下两步:
1、统计每一个字符最后出现的位置
2、从头遍历字符,并更新字符的最远出现下标,如果找到字符最远出现位置下标和当前下标相等了,则找到了分割点
class Solution {
public List<Integer> partitionLabels(String s) {
//统计每个字符最大索引
int[] maxIndex = new int[26];
for(int i=0;i<s.length();i++){
maxIndex[s.charAt(i)-'a'] = i;
}
List<Integer> result = new ArrayList<>();
int left=0;
int right = 0;
for(int i=0;i<s.length();i++){
right= Math.max(right,maxIndex[s.charAt(i)-'a']);//记录当前最远索引
if(i==right){
result.add(right-left+1);
left = right+1;
}
}
return result;
}
}
56. 合并区间
教程视频:https://www.bilibili.com/video/BV1wx4y157nD/?spm_id_from=333.788&vd_source=ddffd51aa532d23e6feac69924e20891
先排序,让所有的相邻区间尽可能的重叠在一起。下文代码是根据左边界升序排序的。
遍历每个区间,如果区间未重叠,直接加入结果数组;
区间重叠,更新当前最小左边界和最大右边界,继续向后遍历。
class Solution {
public int[][] merge(int[][] intervals) {
//按照左边界排序
Arrays.sort(intervals,(a,b)->Integer.compare(a[0],b[0]));
List<int[]> res = new LinkedList<>();
for(int i=1;i<intervals.length;i++){
if(intervals[i-1][1]<intervals[i][0]){
//没有重叠
res.add(intervals[i-1]);
}else{
//更新最小左边界和最大右边界
intervals[i][0] = intervals[i-1][0];
intervals[i][1]=Math.max(intervals[i-1][1],intervals[i][1]);
}
}
res.add(intervals[intervals.length-1]);
return res.toArray(new int[res.size()][]);
}
}
总结
关于区间重合的题目,首先要进行排序,相邻区间尽可能的重叠;
然后判断是寻找重合区间还是非重合区间,确定处理逻辑;
最后编写程序还要注意边界的界定。