435.无重叠区间
讲解链接:代码随想录-435.无重叠区间
首先根据子数组的左边数字排序,然后从 1 开始循环变遍历,如果当前做边界小于前一个数组的右边界,说明这两个数组有重叠,移除数量加 1。注意:此时可能需要更新当前数组的右边界,如果当前数组右边界大于前一个数组右边界,则取前一个数组右边界;因为我们要移除最小数量,所以默认把大的移除,小的保留,以便给下一个数组比较时,就可以保证最少数量。
比如下面这张图,需要移除 2,3,5 数组即可。在出现重叠的时候,右边界值取最小的。
public int eraseOverlapIntervals(int[][] intervals) {
Arrays.sort(intervals, (a, b) -> a[0] - b[0]);
int result = 0;
for (int i = 1; i < intervals.length; i++) {
if (intervals[i][0] < intervals[i - 1][1]) {
result++;
intervals[i][1] = Math.min(intervals[i][1], intervals[i - 1][1]);
}
}
return result;
}
763.划分字母区间
讲解链接:代码随想录-763.划分字母区间
贪心?
因为都是小写字母,所以我们可以创建一个长度 26 的数组,否则可以使用 Map。我们遍历字符串,用字母的 ASCII 值当数组下标,值存放字符串中的下标。因为是顺序遍历,如果字符串中有相同字符,就会记录这个字符的最远下标。
得到数组后,我们创建结果集、一个左边界和右边界,再次遍历字符串,那当前的遍历的字母到之前创建数组中保存的最远下标,更新右边界为最大值,如果遍历到了最大值,就说明可以分割一次了。在添加结果的时候注意边界问题,right - left +1 。left = i + 1 。
public List<Integer> partitionLabels(String s) {
int[] hash = new int[26];
for (int i = 0; i < s.length(); i++) {
hash[s.charAt(i) - 'a'] = i;
}
List<Integer> result = new ArrayList<>();
int left = 0;
int right = 0;
for (int i = 0; i < s.length(); i++) {
right = Math.max(hash[s.charAt(i) - 'a'], right);
if (i == right) {
result.add(right - left + 1);
left = i + 1;
}
}
return result;
}
暴力破解
思路:使用二维集合存储子字符串,主要利用集合的 contains 来判断子集合是否存在当前轮询到的字符串,如果存在则把这个子集合后面的集合全部添加进来并删除,如果不存在就新建一个子数组来保存。
public List<Integer> partitionLabels(String s) {
List<List<Character>> list = new ArrayList<>();
for (int i = 0; i < s.length(); i++) {
Character c = s.charAt(i);
boolean contains = false;
for (int j = 0; j < list.size(); j++) {
List<Character> subList = list.get(j);
if (subList.contains(c)) {
for (int k = j + 1; k < list.size(); k++) {
subList.addAll(list.get(k));
}
for (int k = list.size() - 1; k > j; k--) {
list.remove(k);
}
subList.add(c);
contains = true;
break;
}
}
if (contains) {
continue;
}
List<Character> subList = new ArrayList<>();
subList.add(c);
list.add(subList);
}
return list.stream().map(a -> a.size()).collect(Collectors.toList());
}
56.合并区间
讲解链接:代码随想录-56.合并区间
跟之前的题目类似,重叠则更新区间,否则就添加到结果中,注意在循环外要主动添加最后一个数组。
public int[][] merge(int[][] intervals) {
// 按照左边界排序
Arrays.sort(intervals, (a, b) -> Integer.compare(a[0], b[0]));
List<int[]> results = new ArrayList<>();
for (int i = 1; i < intervals.length; i++) {
// 如果当前数组跟前一个数组有重叠,则更新当前数组的左边界和右边界
if (intervals[i][0] <= intervals[i - 1][1]) {
intervals[i][0] = Math.min(intervals[i][0], intervals[i - 1][0]);
intervals[i][1] = Math.max(intervals[i][1], intervals[i - 1][1]);
} else {
// 没有重叠时就可以保存前一个数组,因为我们一直在更新,所以可以直接保存。
results.add(intervals[i - 1]);
}
}
// 注意这里要在保存一次最后的数组,因为我们在循环中一直保存的是前一个符合数组。
results.add(intervals[intervals.length - 1]);
return results.toArray(new int[results.size()][]);
}