435.无重叠区间
思路
- 自己的:自己的思路是,遍历每个元素,对于i对应的元素,如果比j对应的首元素小,当i尾>j首且i尾<j尾,去掉区间j(标志数组对应为1);当i尾>=j尾,去掉区间i。每个区间与其他所有的比较。—— 思路上可行,但是要注意,应该要按照首元素排序,否则可能因为第一个元素起点过大导致结果不同。
- 题解的:
①元素按照首元素排序,然后从第一个元素开始,让end标志为其尾巴,如果后面的元素头>=end,证明没有相交,且因为按头排序的,所以一个一个比较遇到的正好是第一个满足这种情况的元素,他为下一个不相交区间,end为他的尾巴;如果后面的元素头<end,证明相交了,此时end为两者尾巴小的那个尾巴(同样情况下尽量尾巴要小),去掉区间数加一。
②元素按照尾元素排序,每次尽可能选择尾巴小的。让end为第一个的尾巴,后面的元素,如果头>end,end就为他的尾;如果不是,end不变,因为相交的尾巴肯定比end大,秉承偏好尾巴小,我们直接去掉区间数+1即可。
代码
- 自己的(虽然没通过全部用例)
class Solution {
public int eraseOverlapIntervals(int[][] intervals) {
Arrays.sort(intervals,((o1, o2) -> (o1[0]-o2[0])));
int[] a = new int[intervals.length];
int flag = 0;
for (int i = 0; i < intervals.length; i++) {
for (int j = 0; j<intervals.length; j++) {
if (j != i &&intervals[i][0]<=intervals[j][0] && a[j]==0 && a[i]==0){
if (intervals[i][1]>intervals[j][0] && intervals[i][1]<intervals[j][1]){
a[j]=1;
flag++;
System.out.println(Arrays.toString(intervals[j]));
}else if (intervals[i][1]>intervals[j][0] && intervals[i][1]>=intervals[j][1]){
a[i]=1;
flag++;
System.out.println(Arrays.toString(intervals[i]));
break;
}
}
}
}
return flag;
}
}
这个用例一眼望不到边,但是能到55证明方法可行,只是太笨了。
2. 排序首元素
class Solution {
public int eraseOverlapIntervals(int[][] intervals) {
Arrays.sort(intervals,(o1, o2) -> (o1[0]-o2[0]));
int end = intervals[0][1];
int flag = 0;
for (int i = 1; i < intervals.length; i++) {
if(end<=intervals[i][0])
end=intervals[i][1];
else {
end=Math.min(end,intervals[i][1]);
flag++;
}
}
return flag;
}
}
- 排序尾元素
class Solution {
public int eraseOverlapIntervals(int[][] intervals) {
Arrays.sort(intervals,(o1, o2) -> (o1[1]-o2[1]));
int flag=0;
int end=intervals[0][1];
for (int i = 1; i < intervals.length; i++) {
if (end<=intervals[i][0])
end=intervals[i][1];
else
flag++;
}
return flag;
}
}
技巧
- 数组排序:
①升序排一维:Arrays.sort(ints);
②升序排一维部分:Arrays.sort(ints, 2, 5);
③升序排二维某个下标:Arrays.sort(ints,(o1, o2) -> (o1[1]-o2[1]));
其中[1]指的是下标,按照自己想要的替换。 - 时间范围、区间调度等可参考,且题目需要两个方向考虑时思考能否一个方向贪心(从左到右满足某个条件+从右往左满足另一个,某边满足某个条件即可等)。
- flag设为初始值,在循环中根据条件flag变更值。