LeetCode 435 无重叠区间
题目简析:
求需要去掉几个重叠区间以让剩下的区间无重叠
思路分析:
贪心,看到题目首先反应过来了,按照start来排序
Arrays.sort(数组,Comparator.comparingInt(a->a[0]));
这样排完之后,能尽可能多的把重叠区间靠到一起。而我们也不需要真的去掉重叠区间,就用一个变量来记录一下当前最小右极限即可
而求最小左区间如果不理解,可以看下面这个示例
[[1,12],[6,13],[12,15],[15,16]]
pre==12在与6比较后一定要去掉一个,而若直接替换成13,则后续还会继续去掉一个区间,为此要求一个最小的
public int eraseOverlapIntervals(int[][] intervals) {
//升序
Arrays.sort(intervals, Comparator.comparingInt(a -> a[0]));
int count = 0;
//记录最左的右极限,若碰到需要移除的,则记录移除和上一个的最小左区间
int pre = intervals[0][1];
for (int i = 1; i < intervals.length; i++) {
if(pre>intervals[i][0]){
count++;
//记录最小左区间
pre = Math.min(pre,intervals[i][1]);
}else {
//非重叠,更换最小左区间
pre = intervals[i][1];
}
}
return count;
}
LeetCode 763划分字母区间
题目简析:
把一个字符串划分为尽可能多的片段,同一字母最多出现在一个片段中。
注意,划分结果需要满足:将所有划分结果按顺序连接,得到的字符串仍然是 s
。
返回一个表示每个字符串片段的长度的列表
思路分析:
题目已经说了分割的字符串连接后依然是s,那么很明显不能对原s进行操作,这道题其实说是区间,我自然而然就想到了,找每一段中,字母所能到达的最远位置,类似找最远区间。
如何记录字母所能到达的最远距离呢?在一个for里去操作(这一点是新学的知识点)
edge[chars[i]-'a'] = i;
记录好最远位置后,接下来的难题就是如何找到分割点
因为找到了某一段中的最远可达距离,那么当循环的i==这个距离后就证明找到了分割点,记录好后从分割点作为起始点再去往后找
public List<Integer> partitionLabels(String s) {
//因为同一字母最多出现在一个片段中
List<Integer> list = new LinkedList<>();
int []edge = new int[26];
char[] chars = s.toCharArray();
//统计每个字符所到达的最远位置
for (int i = 0; i < chars.length; i++) {
edge[chars[i]-'a'] = i;
}
int left = 0;
int right = 0;
//去找当前段能找到的最远位置的字符
for (int i = 0; i < chars.length; i++) {
right = Math.max(right,edge[chars[i] - 'a']);
if(right == i){
list.add(right-left+1);
left = i+1;
}
}
return list;
}
LeetCode 56合并区间
题目简析:
合并所有重叠的区间,并返回 一个不重叠的区间数组,该数组需恰好覆盖输入中的所有区间
思路分析:见注释
public int[][] merge(int[][] intervals) {
//本题类似435
List<int[]> list = new LinkedList<>();
//排序,重叠的靠近---按左极限排
Arrays.sort(intervals, Comparator.comparingInt(a->a[0]));
//这次是需要记录最小左极限,最大右极限---初始化为1
int left = intervals[0][0];
int right = intervals[0][1];
//循环中去查找---已经记录了第一个,i从1开始
for (int i = 1; i < intervals.length; i++) {
//下一个的左极限大于记录的右极限,无法合并,重新记录,新一轮比较
if(right<intervals[i][0]){
list.add(new int[]{left,right});
//若最后一个位置是独立的则无法继续add了,因此可能要在for后add一次
left = intervals[i][0];
right = intervals[i][1];
}else {
//右极限大于等于下一左极限,说明重叠,要合并
right = Math.max(right,intervals[i][1]);
}
}
//最后一个位置还没有比较
list.add(new int[]{left,right});
return list.toArray(new int[list.size()][]);
}