435. 无重叠区间
思路:
两个思考角度,都是右边界升序排列。
1、找需要删除的区间,右边界越小,接触到重叠区间的机会就越少,所以碰到重叠的(左边界<目前不重叠区间右边界)就是需要删除的区间,
2、找最多不重叠的区间,右边界越小,留给其他不重叠区间的机会就越多,所以碰到不重叠的,不重叠区间数就+1.
代码:
1、直接删除重复区间
class Solution {
public int eraseOverlapIntervals(int[][] intervals) {
int res = 0;
//区间右边界升序排序
Arrays.sort(intervals, (a, b) -> {
return Integer.compare(a[1], b[1]);
});
int right = intervals[0][1];
//直接计算需要删除的区间
for(int i = 1; i < intervals.length; i++){
//本区间与上一个区间没有重叠,将最右边界更新
if(intervals[i][0] >= right){
right = intervals[i][1];
}else{//有重叠res+1,表示删除本区间,最右边界保持不变
res++;
}
}
return res;
}
}
2、找到最多不重叠的区间,然后用总区间数减去此值
class Solution {
public int eraseOverlapIntervals(int[][] intervals) {
int res =1;
//区间右边界升序排序
//因为按照右边界从小到大的顺序遍历,留给不重叠区间的空就越大,从而找到最多不重叠的区间
Arrays.sort(intervals, (a, b) -> {
return Integer.compare(a[1], b[1]);
});
int right = intervals[0][1];
//找最多不重叠的区间
for(int i = 1; i < intervals.length; i++){
//本区间与上一个区间没有重叠
if(intervals[i][0] >= right){
right = intervals[i][1];
res++;
}else{//有重叠就跳过
continue;
}
}
return intervals.length - res;
}
}
需要注意的点:
1、排序代码的写法
2、找最多不重复区间的计数要从1开始算
763.划分字母区间
思路:
记录每个字母最后出现的位置,遍历当前数组,更新右区间为正在遍历字母的最大位置,表示要包含前面所有的字母,至少要到什么位置,一但到达该位置,结果就多了一条区间记录,并更新起点。
代码:
class Solution {
public List<Integer> partitionLabels(String s) {
List<Integer> res = new LinkedList<>();
char[] c = s.toCharArray();
//记录26个字母最后出现的位置
int[] edge = new int[26];
for(int i = 0; i < c.length; i++){
edge[c[i] - 'a'] = i;
}
int start = -1;//要输出个数,所以要从-1开始算
int idx = 0;
for(int i = 0; i < c.length; i++){
//idx表示遍历到的字母最后出现的位置
idx = Math.max(idx, edge[c[i] - 'a']);
if(i == idx){
res.add(idx - start);
start = i;
}
}
return res;
}
}
需要注意的点:
·1、遍历字母数组即可记录每个字母出现的最后位置。
2、因为要记录的是区间长度,所以左区间的初始值为-1。
56. 合并区间
思路:
代码:
class Solution {
public int[][] merge(int[][] intervals) {
//左边界升序排列
Arrays.sort(intervals, (a, b) -> {
return Integer.compare(a[0], b[0]);
});
List<int[]> res = new LinkedList<>();
int left = intervals[0][0];
int mostright = intervals[0][1];
for(int i = 1; i < intervals.length; i++){
//可以形成重叠区间
if(intervals[i][0] <= mostright){
mostright = Math.max(mostright, intervals[i][1]);
}else{//不能重叠
res.add(new int[]{left, mostright});//加入之间重叠的区间
left = intervals[i][0];
mostright = intervals[i][1];
}
}
//无论最后一个区间是否与之前形成重叠区间,最后一个重叠区间都需要加上
res.add(new int[]{left, mostright});
return res.toArray(new int[res.size()][]);
}
}