452.用最少数量的箭引爆气球
代码随想录
思路:求points数组交集的数量。
代码:points按照左边界排序,让相邻气球尽可能挨在一起
如果i气球的左边界大于i-1的右边界,一定不重叠,添加弓箭数
若i气球的左边界小于等于i-1的左边界,这两个一定重叠,
但问题是还需要判断和下一个气球是否重叠,更新右边界(取这两个气球的最小右边界),与下一个气球进行比较。
关于排序比较写法:
在关于身高重建队伍中:
// 身高从大到小排(身高相同k小的站前面)
Arrays.sort(people, (a, b) -> {
if (a[0] == b[0]) return a[1] - b[1]; // a - b 是升序排列,故在a[0] == b[0]的狀況下,會根據k值升序排列
return b[0] - a[0]; //b - a 是降序排列,在a[0] != b[0],的狀況會根據h值降序排列
});
因此如果按照这样写,会有溢出错误:
Arrays.sort(points,(o1,o2)->{
return o1[0]-o2[0];
});
正确写法:
// 根据气球直径的开始坐标从小到大排序
// 使用Integer内置比较方法,不会溢出
Arrays.sort(points, (a, b) -> Integer.compare(a[0], b[0]));
代码
class Solution {
public int findMinArrowShots(int[][] points) {
Arrays.sort(points,(o1,o2)->Integer.compare(o1[0],o2[0]));
int count = 0;
for(int i = 1;i< points.length;i++){
if(points[i][0]>points[i-1][1]){
count++;//当前气球左边界大于上一个气球右边界,一定不重合
}else{
points[i][1] = Math.min(points[i-1][1],points[i][1]);//更新当前气球的右边界
}
}
return count+1;
}
}
453.无重叠区间
代码随想录
和452题很像,只需要计数,无需更新区间。所以基本思路是:
按照左边界排序,如果重叠则将当前右边界改为两者之中最小的,同时要删除数+1;如果不重叠正常循环直到下一个重叠区间。
即:若有重叠,移除右边界大的那个区间,代码上体现在更新当前区间的右边界
代码
class Solution {
public int eraseOverlapIntervals(int[][] intervals) {
Arrays.sort(intervals,(o1,o2)->Integer.compare(o1[0],o2[0]));
int count = 0;
for(int i = 1;i<intervals.length;i++){
if(intervals[i][0]>=intervals[i-1][1]){
continue;
}else{
intervals[i][1] = Math.min(intervals[i-1][1],intervals[i][1]);
count++;
}
}
return count;
}
}
763.划分字母区间
代码随想录
在遍历过程中找到每个字母的最远边界,如果找到之前遍历过的所有字母的最远边界,那么就到达分割点了。步骤如下:
- 统计每个字符最后出现的位置
- 从头遍历字符,并更新字符的最远出现下标,如果找到字符最远出现位置下标和当前下标相等,则找到了分割点。
代码
class Solution {
public List<Integer> partitionLabels(String s) {
List<Integer> result = new ArrayList<>();
int[] hash = new int[26];
//求解最远距离
for (int i = 0; i < s.length(); i++) {
hash[s.charAt(i)-'a'] = i;
}
int left = 0;
int right = 0;
for(int i = 0; i < s.length(); i++){
right = Math.max(hash[s.charAt(i)-'a'],right);
if(right==i){
result.add(right-left+1);
left = i + 1;
}
}
return result;
}
}
关于求解最远距离:
可以用不断覆盖的代码技巧:
//求解最远距离
for (int i = 0; i < s.length(); i++) {
hash[s.charAt(i)-'a'] = i;
}
或者调用API:
right = Math.max(s.lastIndexOf(s.charAt(i)),right);
点进入源码是倒序找到第一个待查找字母,返回其下标:
public int lastIndexOf(int ch, int fromIndex) {
if (ch < Character.MIN_SUPPLEMENTARY_CODE_POINT) {
// handle most cases here (ch is a BMP code point or a
// negative value (invalid code point))
final char[] value = this.value;
int i = Math.min(fromIndex, value.length - 1);
for (; i >= 0; i--) {
if (value[i] == ch) {
return i;
}
}
return -1;
} else {
return lastIndexOfSupplementary(ch, fromIndex);
}