代码随想录 452. 用最少数量的箭引爆气球、435. 无重叠区间 、 763.划分字母区间

452. 用最少数量的箭引爆气球

题目

参考文章

思路:气球边界问题

这里先按气球区间的左边界从小到大排序,由题目可知 xstart<=x<=xend,所以要看当前气球区间的左边界和上一个气球有边界,如果它们不是紧挨着的,就发射的箭数+1;如果是紧挨着的,就更新当前气球区间的右边界为当前气球区间和前一个气球区间的最小右边界,这里为什么要最小右边界呢?因为题目说的是要只能是同一支箭,所以如果不取最小右边界的话,即使是下一轮比较是紧挨着的都不可能是同一支箭。

代码:

class Solution {
    public int findMinArrowShots(int[][] points) {
         // 根据气球直径的开始坐标从小到大排序
        // 使用Integer内置比较方法,不会溢出
        Arrays.sort(points, (a, b) -> Integer.compare(a[0], b[0]));

        int count=1;//箭的数量,points不为空就一定有一支箭
        for(int i=1;i<points.length;i++){
            if(points[i][0]>points[i-1][1]){//当两个气球不紧挨着的时候,表示要射出两支或以上的箭,因为xstart<=x<=xend,所以只要边界左边界与上一个气球的右边界相同都会只能是同一支箭。所以只能是>号,不能是>=号
                count++;
            }else{//如果紧挨着,就更新当前气球的右边界,方便与下一个气球的左边界比较,查看是否是紧挨着的,判断是否可以用同一支箭射爆
                points[i][1]=Math.min(points[i][1],points[i-1][1]);
            }
        }

        return count;
    }
}

435. 无重叠区间

题目

参考文章

思路:左边界排序,然后找当前区间的左边界比上一个区间的右边界小的就删除,并更新两个重叠区间的最小右边界,因为取最小右边界,这个最小右边界作为当前区间的右边界和下一个区间的左边界比较,如果和最小右边界都重叠了,肯定两个区间都重叠了,所以也是要删除该重叠区间的。

代码:

class Solution {
    public int eraseOverlapIntervals(int[][] intervals) {
          Arrays.sort(intervals, (a,b)-> {
            return Integer.compare(a[0],b[0]);
        });

        int count=0;//默认没有重叠区间
        for(int i=1;i<intervals.length;i++){
            if(intervals[i-1][1]>intervals[i][0]){//i从1开始,如果上一个区间的右边界和当前区间左边界比较,如果大于就发生了重叠,就count++,而且更新当前区间的右边界为两个区间的最小右边界,因为要判断后面的区间与当前的重叠区间是否继续重叠,如果重叠就继续删除(即count++)
                count++;
                intervals[i][1]=Math.min(intervals[i-1][1],intervals[i][1]);
            }
        }
        return count;
    }
}

763.划分字母区间

题目

参考文章

思路:就是把当前遇到的元素的出现的最远距离的下标给表示出来,当此前下标下,其之前的元素的最远位置都小于这个下标的,就都可以截断为一个区间了。然后再判断后面的元素区间是否满足如上所述的情况

这里寻找最远距离下标,就是通过一个循环实现,用edge[chars[i]-'a'],找到最后出现该字母的下标

而last为-1,是因为它本来就是以下标来比较,所以设置为-1是合理的,后面重置last=i,也是这个原理。

为什么可以直接是idx==i呢?因为前面说到,当前得到的元素的位置是最远的出现位置,其前面的元素的最远出现位置不可能大于当前得到元素的最远位置(因为Math.max),所以可以直接idx==i来判断

代码:

class Solution {
    public List<Integer> partitionLabels(String s) {
        List<Integer> list = new LinkedList<>();
        int[] edge = new int[26];
        char[] chars=s.toCharArray();
        for(int i=0;i<chars.length;i++){
            edge[chars[i]-'a']=i;//寻找最远位置下标的循环
        }

        int idx=0;
        int last=-1;
        for(int i=0;i<chars.length;i++){
            idx=Math.max(idx,edge[chars[i]-'a']);//找到当前下标下元素的最后出现的位置,然后和当前的i进行比较,如果和i相等,就是分割点了。
            if(idx==i){
                list.add(i-last);
                last=i;
            }
        }
        return list;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值