435. 无重叠区间
按照左边界排序,从左向右记录交叉区间的个数
class Solution {
public int eraseOverlapIntervals(int[][] intervals) {
//如果二维数组长度为0,直接返回
if (intervals.length == 0) return 0;
//区间按左边界排序
Arrays.sort(intervals, (a,b)-> {
return Integer.compare(a[0],b[0]);
});
int remove = 0;
int pre = intervals[0][1];
for (int i = 1; i < intervals.length; i++) {
if (intervals[i][0] < pre) {//交叉区间
remove++;
pre = Math.min(pre, intervals[i][1]);
} else {
pre = intervals[i][1];
}
}
return remove;
}
}
763. 划分字母区间
在遍历的过程中相当于是要找每一个字母的边界,如果找到之前遍历过的所有字母的最远边界,说明这个边界就是分割点了。此时前面出现过所有字母,最远也就到这个边界了。
可以分为如下两步:
- 统计每一个字符最后出现的位置
- 从头遍历字符,并更新字符的最远出现下标,如果找到字符最远出现位置下标和当前下标相等了,则找到了分割点
class Solution {
public List<Integer> partitionLabels(String s) {
int[] edge = new int[26];
char[] str = s.toCharArray();
//统计字符串中每个字母出现的最远位置
for (int i = 0; i < str.length; i++) {
edge[str[i] - 'a'] = i;
}
List<Integer> list = new LinkedList<>();
int last = 0; //记录字母右边界
int start = -1; //记录下一字符串起始位置
for (int i = 0; i < str.length; i++) {
last = Math.max(last, edge[str[i] - 'a']);
//到达最远边界
if (i == last) {
list.add(i - start);
start = i;
}
}
return list;
}
}
56. 合并区间
按照左边界从小到大排序之后,如果 intervals[i][0] <= intervals[i - 1][1]
即intervals[i]的左边界 <= intervals[i - 1]的右边界,则一定有重叠。
用合并区间后左边界和右边界,作为一个新的区间,加入到result数组里就可以了。如果没有合并就把原区间加入到result数组。
class Solution {
public int[][] merge(int[][] intervals) {
//区间按左边界排序
Arrays.sort(intervals, (a,b)-> {
return Integer.compare(a[0],b[0]);
});
List<int[]> result = new LinkedList<>();
//
int left = intervals[0][0];
int right = intervals[0][1];
for (int i = 1; i < intervals.length; i++) {
//重叠区间,更新最大右边界
if (intervals[i][0] <= right) {
right = Math.max(right, intervals[i][1]);
} else {
//非重叠区间
result.add(new int[]{left, right});
left = intervals[i][0];
right = intervals[i][1];
}
}
//将最后一个区间加入数组
result.add(new int[]{left, right});
return result.toArray(new int[result.size()][]);
}
}