力扣面试150题--插入区间和用最少数量的箭引爆气球

Day 28

题目描述

在这里插入图片描述

思路

初次思路:借鉴一下昨天题解的思路,将插入的区间与区间数组作比较,插入到升序的数组中,其他的和(合并区间)做法一样。
注意需要特殊处理一下情况,插入区间比数组中最后一个区间的起始点大,这种情况,在循环中不会计算到插入区间,单独处理一下。

class Solution {
    public int[][] insert(int[][] intervals, int[] newInterval) {
        List<int[]> merged = new ArrayList<int[]>();
        if(intervals.length==0){//区间数组为空
            merged.add(new int[]{newInterval[0],newInterval[1]});
            return merged.toArray(new int[merged.size()][]);   
        }
        int start=0,end=0;
        for (int i = 0; i < intervals.length;i++) {
            if(newInterval[0]<intervals[i][0]) {//将插入区间到数组中
                 start = newInterval[0];
                 end = newInterval[1];
                 newInterval[0] = intervals[i][0];
                 newInterval[1] = intervals[i][1];
                 i--;
            }
            else{
                 start = intervals[i][0];
                 end = intervals[i][1];
            }
            if(merged.size()==0||merged.get(merged.size()-1)[1]<start) {
                merged.add(new int[]{start, end});
            }
            else{
                merged.get((merged.size()-1))[1] = Math.max(merged.get(merged.size()-1)[1], end);
            }
        }
         if(newInterval[0]>=intervals[intervals.length-1][0]){//特殊处理一下
            if(merged.size()==0||merged.get(merged.size()-1)[1]<newInterval[0]) {
                merged.add(new int[]{newInterval[0], newInterval[1]});
            }
            else{
                merged.get((merged.size()-1))[1] = Math.max(merged.get(merged.size()-1)[1], newInterval[1]);
            }
        }
        return merged.toArray(new int[merged.size()][]);   
    }
}

问题:时间复杂度比较高,虽然通过了
做法:注意题目条件,给定的区间数组中的区间是不重叠的,那么我们需要插入一个新的区间,只需要找到这个与这个插入区间有重叠的区间,合并成一个大区间即可。

class Solution {
    public int[][] insert(int[][] intervals, int[] newInterval) {
         List<int[]> res = new ArrayList<int[]>();
         if(intervals.length==0){//数组为空特殊处理
            res.add(new int[]{newInterval[0],newInterval[1]});
            return res.toArray(new int[res.size()][]);
         }
         int x=0;
        int start =newInterval[0],end=newInterval[1];//初始化
        for (int i = 0; i < intervals.length; i++) {
            if(intervals[i][1] <newInterval[0]) {
                //说明这个区间和新插入区间没有交集
                res.add(new int[]{intervals[i][0],intervals[i][1]});
            }
            else if(intervals[i][0] > newInterval[1]) {
                if(x==0){
            //由于数组是按照起始点的升序排列。证明插入的区间到这里已经找到最大的合并区间
                    res.add(new int[]{start,end});
                    x=1;
                }
                //说明这个区间和新插入区间没有交集
                 res.add(new int[]{intervals[i][0],intervals[i][1]});
            }
            else{
            //扩大合并区间
                start=Math.min(start,intervals[i][0]);
                end=Math.max(end,intervals[i][1]);
            }
        }
        if(x==0){
        //排除特殊情况,即为数组中所有区间在插入这个区间后合并为一个大区间
             res.add(new int[]{start,end});
        }
        return res.toArray(new int[res.size()][]);
    }
}

题目描述

在这里插入图片描述

思路

首先我们来中翻中一下:这题所谓的最少数量的箭,可以理解为多个区间中的重叠的区间,所以这道题的目的是为了找到这个区间数组有几个重叠区间。
做法

  1. 将所有气球按照起始点升序进行排序
  2. 创建start和end,用来记录当前重合区间的范围(初始设置为第一个气球的范围),初始设置箭数sum为1。
  3. 从前向后遍历,由于此时气球是有序的,比较当前气球和重合范围(start,end)是否重合,也就是比较当前气球的起始点是否小于等于end(不比较start的原因在于是升序的,下一个气球的起始点一定比start大
  4. 如果小于等于end,说明气球在重合区间,需要更新重合区间(这里建议画图理解),更新看代码。
  5. 如果大于end,说明这个气球和之前的所有气球不能一箭射穿,就将箭数加1
    注意:箭初始设置为1,目的就是将与第一个气球有重合区间的所有气球都射穿,如果一个气球不在重合区间,就需要多一把箭。
class Solution {
    public int findMinArrowShots(int[][] points) {
        if(points.length==0){//为空特殊处理
           return  0;
        }
        int start=0,end=0,sum=1;
        Arrays.sort(points, new Comparator<int[]>() {//按照起始点进行升序排序
            public int compare(int[] interval1, int[] interval2) {
                return Integer.compare(interval1[0], interval2[0]);
            }
        });//排序
        start=points[0][0];
        end=points[0][1];
        for(int i=1;i<points.length;i++){
            if(points[i][0]<=end){
            //如果该区间的起始点比目前记录的区间结束点还小,说明有重合
                start=Math.max(start,points[i][0]);//修改区间的起始点
                end=Math.min(end,points[i][1]);//修改区间的结束点
                //这里就是收缩到目前的最小重合区间
            }
            else{//说明这个气球不在之前的重合区间,一箭射不爆
                sum++;//计数器加1 
                start=points[i][0];
                end=points[i][1];
                //将这个气球的范围作为新的区间
            }
        }
        return sum;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值