持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第26天,点击查看活动详情
本文包含以下几题:
- 根据身高重建队列。现有一群打乱的队列,数组中第一个元素代表人的身高,第二个代表前面比他高或者和他一样高的还有几个,要求重建队列。
- 给定一个区间,要求移除区间内某些集合使得区间不重合。
- 给定区间,引爆区间内气球。
解题思路
LeetCode 406 根据身高重建队列
根据本题要求,首先需要明确的是肯定需要排序,那问题就是如何排序了。
假设按照身高从矮到高排序,那假设当前序列为[[7,0],[4,4],[7,1],[5,0],[6,1],[5,2]]则排序结果为:[[4,4],[5,0],[5,2],[6,1],[7,0],[7,1]]。
此时好像并没有什么规律,那试着按照第二个元素排序:[[5,0],[7,0],[6,1],[7,1],[5,2],[4,4]]。此时和结果已经有点像了,但无论怎么模拟打都无法的得到最终结果。再试一次,按照身高从高往低排序:[[7,0],[7,1],[6,1],[5,0],[5,2],[4,4]]。
此时我们通过后面索引依次插入到序列,可以发现刚好满足。那为什么不能从矮到高再插入呢?因为此时插入矮的会影响后面高的插入,但如果插入高的矮的再插入则不会影响结果。根据此思路得到代码:
public int[][] reconstructQueue(int[][] people) {
ArrayList<int[]> res = new ArrayList<>();
Arrays.sort(people, (o1, o2) -> {
if(o1[0] == o2[0]) return o1[1]-o2[1];
return o2[0]-o1[0];
});
for (int[] person : people) {
res.add(person[1], person);
}
return res.toArray(new int[0][]);
}
LeetCode 435 无重叠区间
本题的思路较为简单,区间不重叠无非就是当前区间的第一个数字大于等于前一个区间的第二个数字,那如何完成移除动作呢?
其实我们只需要判断区间是否重叠,如果重叠就将此区间的第二个数字替代为前一个的即可,此种方式是根据首先排序左边在排序右边的方式,也可以只排序左边,之后根据当前第二个和前一个第二个数值取最小的即可。本质都是一样的,代码如下:
public int eraseOverlapIntervals(int[][] intervals) {
int count = 0;
Arrays.sort(intervals, (o1,o2) -> Integer.compare(o1[0],o2[0]));
// 或者这样排序,下面也需要变化
// Arrays.sort(intervals, (o1,o2) -> {
// if(o1[0]==o2[0]) return o1[1]-o2[1];
// return o1[0]-o2[0];
// });
for(int i=1;i<intervals.length;i++){
if(intervals[i][0]<intervals[i-1][1]){
count++;
intervals[i][1] = Math.min(intervals[i][1], intervals[i-1][1]);
// 此处对应第二种排序
// intervals[i][1] =intervals[i-1][1];
}
}
return count;
}
LeetCode 452 用最少数量的箭引爆气球
本题和上题思路一致,都是通过判断区间,本题只需要判断有几个重叠区间即可,代码如下:
public int findMinArrowShots(int[][] points) {
Arrays.sort(points, (o1, o2) -> Integer.compare(o1[0],o2[0]));
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], points[i-1][1]);
}
}
return count;
}