学习内容
力扣算法
452. 用最少数量的箭引爆气球
435. 无重叠区间
763.划分字母区间
56. 合并区间
具体内容
452. 用最少数量的箭引爆气球
在二维空间中有许多球形的气球。对于每个气球,提供的输入是水平方向上,气球直径的开始和结束坐标。由于它是水平的,所以纵坐标并不重要,因此只要知道开始和结束的横坐标就足够了。开始坐标总是小于结束坐标。
一支弓箭可以沿着 x 轴从不同点完全垂直地射出。在坐标 x 处射出一支箭,若有一个气球的直径的开始和结束坐标为 xstart,xend, 且满足 xstart ≤ x ≤ xend,则该气球会被引爆。可以射出的弓箭的数量没有限制。 弓箭一旦被射出之后,可以无限地前进。我们想找到使得所有气球全部被引爆,所需的弓箭的最小数量。
给你一个数组 points ,其中 points [i] = [xstart,xend] ,返回引爆所有气球所必须射出的最小弓箭数。
示例 1:
输入:points = [[10,16],[2,8],[1,6],[7,12]] 输出:2 解释:对于该样例,x = 6 可以射爆 [2,8],[1,6] 两个气球,以及 x = 11 射爆另外两个气球
做题思路
先以每个数组的第一个元素进行排序,然后再通过后一个数组的第一个元素与前一个数组的最后一个元素进行比较;为了防止后一组重叠上两组,因此将最小边界值赋值给上一组的最后一个元素
解题
class Solution {
public int findMinArrowShots(int[][] points) {
//按第一个元素从小到大排列
Arrays.sort(points,(a,b) -> Integer.compare(a[0],b[0]));
//默认第一个也为1
int count = 1;
//后一个与前一个进行比较
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;
}
}
435. 无重叠区间
给定一个区间的集合 intervals ,其中 intervals[i] = [starti, endi] 。返回 需要移除区间的最小数量,使剩余区间互不重叠 。
示例 1:
输入: intervals = [[1,2],[2,3],[3,4],[1,3]] 输出: 1 解释: 移除 [1,3]
后,剩下的区间没有重叠。
做题思路
遇上一道题目类似
解题
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]){
continue;
}else{
count++;
intervals[i][1] = Math.min(intervals[i][1],intervals[i-1][1]);
}
}
return count;
}
}
763.划分字母区间
字符串 S 由小写字母组成。我们要把这个字符串划分为尽可能多的片段,同一字母最多出现在一个片段中。返回一个表示每个字符串片段的长度的列表。
示例:
输入:S = "ababcbacadefegdehijhklij" 输出:[9,7,8] 解释: 划分结果为 "ababcbaca", "defegde", "hijhklij"。 每个字母最多出现在一个片段中。 像 "ababcbacadefegde", "hijhklij" 的划分是错误的,因为划分的片段数较少。
做题思路
通过找到之前遍历过的所有字母的最远边界,则获得一个分割点。此时前面出现过所有字母,最远也就到这个边界了。从而获得全局最优
解题
class Solution {
public List<Integer> partitionLabels(String s) {
//将s转化为char类型
char[] s1 = s.toCharArray();
//存放结果集
List<Integer> list = new ArrayList<>();
//存放字母
int[] edge = new int[26];
for (int i = 0; i < s1.length; i++) {
//每个字母对应的数
edge[s1[i] - 'a'] = i;
}
int idx = 0;
//last表示求第二个区间的差值
int last = -1;
for (int i = 0; i < s1.length; i++) {
//取最远距离
idx = Math.max(idx,edge[s1[i] - 'a']);
if (i == idx) {
list.add(i - last);
last = i;
}
}
return list;
}
}
56. 合并区间
给出一个区间的集合,请合并所有重叠的区间。
示例 1:
输入: intervals = [[1,3],[2,6],[8,10],[15,18]] 输出: [[1,6],[8,10],[15,18]] 解释: 区间 [1,3] 和 [2,6] 重叠, 将它们合并为 [1,6].
示例 2:
输入: intervals = [[1,4],[4,5]] 输出: [[1,5]] 解释: 区间 [1,4] 和 [4,5] 可被视为重叠区间。 注意:输入类型已于2019年4月15日更改。 请重置默认代码定义以获取新方法签名。
做题思路
通过判断区间是否有重叠
解题
class Solution {
public int[][] merge(int[][] intervals) {
List<int[]> res = new LinkedList<>();
//按照左边界排序
Arrays.sort(intervals, (x, y) -> Integer.compare(x[0], y[0]));
//initial start 是最小左边界
int start = intervals[0][0];
int rightmostRightBound = intervals[0][1];
for (int i = 1; i < intervals.length; i++) {
//如果左边界大于最大右边界
if (intervals[i][0] > rightmostRightBound) {
//加入区间 并且更新start
res.add(new int[]{start, rightmostRightBound});
start = intervals[i][0];
rightmostRightBound = intervals[i][1];
} else {
//更新最大右边界
rightmostRightBound = Math.max(rightmostRightBound, intervals[i][1]);
}
}
//哪怕上述程序不执行 也一定有一个空的区间
res.add(new int[]{start, rightmostRightBound});
return res.toArray(new int[res.size()][]);
}
}