力扣题目链接
给定一个区间的集合,找到需要移除区间的最小数量,使剩余区间互不重叠。
注意: 可以认为区间的终点总是大于它的起点。 区间 [1,2] 和 [2,3] 的边界相互“接触”,但没有相互重叠。
示例 1:
示例 2:
示例 3:
输入: [ [1,2], [2,3] ]
输出: 0
解释: 你不需要移除任何区间,因为它们已经是无重叠的了。
相信很多同学看到这道题目都冥冥之中感觉要排序,但是究竟是按照右边界排序,还是按照左边界排序呢?
其实都可以。主要就是为了让区间尽可能的重叠。
我来按照右边界排序,从左向右记录非交叉区间的个数。最后用区间总数减去非交叉区间的个数就是需要移除的区间个数了。
此时问题就是要求非交叉区间的最大个数。
和射气球差不多
按照左边界排序 代码如下:
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][0]<intervals[i-1][1]){
//取最小的右边界
intervals[i][1]=Math.min(intervals[i][1],intervals[i-1][1]);
//重合 需要删一个
count++;
}
}
return count;
}
}
力扣题目链接
字符串 S 由小写字母组成。我们要把这个字符串划分为尽可能多的片段,同一字母最多出现在一个片段中。返回一个表示每个字符串片段的长度的列表。
示例:
提示:
S的长度在[1, 500]之间。
S只包含小写字母 ‘a’ 到 ‘z’ 。
在遍历的过程中相当于是要找每一个字母的边界,如果找到之前遍历过的所有字母的最远边界,说明这个边界就是分割点了。此时前面出现过所有字母,最远也就到这个边界了。
可以分为如下两步:
如图:
明白原理之后,代码并不复杂,如下:
class Solution {
public List<Integer> partitionLabels(String S) {
List<Integer> list = new LinkedList<>();
int[] edge = new int[27]; //记录最远出现位置
char[] chars = S.toCharArray();
//从前向后遍历
for (int i = 0; i < chars.length; i++) {
edge[chars[i] - 'a'] = i; //统计每个字母出现的最远位置 覆盖
}
int right = 0;
int left = 0;
for (int i = 0; i < chars.length; i++) {
right = Math.max(right,edge[chars[i] - 'a']);// 找到字符出现的最远边界
if (i == right) {
list.add(right-left+1); //统计个数
left=i+1; //去下一个区间
}
}
return list;
}
}
力扣题目链接
给出一个区间的集合,请合并所有重叠的区间。
示例 1:
示例 2:
输入: intervals = [[1,4],[4,5]]
输出: [[1,5]]
解释: 区间 [1,4] 和 [4,5] 可被视为重叠区间。
注意:输入类型已于2019年4月15日更改。 请重置默认代码定义以获取新方法签名。
本题的本质其实还是判断重叠区间问题。
和气球 无重叠区间思路相
/**
时间复杂度 : O(NlogN) 排序需要O(NlogN)
空间复杂度 : O(logN) java 的内置排序是快速排序 需要 O(logN)空间
*/
class Solution {
public int[][] merge(int[][] intervals) {
//应该有一个判断非空,不写也过了
LinkedList<int[]> res=new LinkedList<>();//放结果
//按左边界排序
Arrays.sort(intervals,(a,b) -> Integer.compare(a[0],b[0]));
res.add(intervals[0]); //结果集里一定有一个区间 (看做上一个区间)
for(int i=1;i<intervals.length;i++){
if(intervals[i][0]<=res.getLast()[1]){
//上一个区间的左边界一定是最小的,只更新右边界 去最大的
res.getLast()[1]=Math.max(intervals[i][1],res.getLast()[1]);
}else{
res.add(intervals[i]); //区间不重叠 直接把区间放进来
}
}
return res.toArray(new int[res.size()][]);
}
}