【贪心算法4】

力扣452.用最少数量的剪引爆气球

链接: link

思路

这道题的第一想法就是如果气球重叠得越多那么用箭越少,所以先将气球按照开始坐标从小到大排序,遇到有重叠的气球,在重叠区域右边界最小值之前的区域一定需要一支箭,这道题有两个地方容易出错:

1.出现重叠区域,忘记更新最右边气球的有边界;

2.在重叠区域内射箭,即在下面提供的代码中else里执行res++;

这是我自己容易犯的错

javascript 复制代码
class Solution {
    public int findMinArrowShots(int[][] points) {
        if (points.length == 0)
            return 0;
        Arrays.sort(points, (a, b) -> Integer.compare(a[0], b[0]));
        int res = 1;// 气球数组不为0,至少需要一支箭
        for (int i = 1; i < points.length; i++) {
            // 当前气球开始位>前一个气球的结束位置
            if (points[i][0] > points[i - 1][1]) {
                res++;
            } else {
                // 否则当前气球和前一个气球挨着
                // 更新当前气球的有边界,瑜前一个气球比较
                // 更新是为了避免和后一个气球比较的时候重复射箭
                points[i][1] = Math.min(points[i][1], points[i - 1][1]);
            }
        }
        return res;
    }
}

435.无重叠区间

链接: link

javascript 复制代码
class Solution {
    public int eraseOverlapIntervals(int[][] intervals) {
        if (intervals.length == 1)
            return 0;
        // 按照右边界排序,从前向后遍历
        Arrays.sort(intervals, (a, b) -> Integer.compare(a[1], b[1]));
        int cnt = 1;// 统计重合区域
        for (int i = 1; i < intervals.length; i++) {
            // 当前节点的左边界<前一个节点的右边界,一定有重合
            if (intervals[i][0] < intervals[i - 1][1]) {
                // 更新当前节点右边界
                intervals[i][1] = Math.min(intervals[i][1], intervals[i - 1][1]);
            } else {
                // 当前节点和前一个节点没有重合
                cnt++;
            }
        }
        return intervals.length - cnt;
    }
}

相似题型

763.划分字母区间

链接: link

javascript 复制代码
class Solution {
    public List<Integer> partitionLabels(String s) {
        List<Integer> ls = new ArrayList<>();
        int[] edge = new int[26];
        char[] chars = s.toCharArray();
        for (int i = 0; i < chars.length; i++) {
            edge[chars[i] - 'a'] = i; // 记录每个字母最大边界
        }
        int left = 0, right = 0;
        for (int i = 0; i < chars.length; i++) {
            right = Math.max(right, edge[chars[i] - 'a']);
            if (i == right) {
                ls.add(i - left + 1);
                left = right + 1;
            }
        }
        return ls;
    }
}

56.合并区间

链接: link

思路

这种题本质和【贪心算法4】的452和435一样的套路,这几道题都是判断区间重叠,区别就是判断区间重叠后的逻辑,本题是判断区间重贴后要进行区间合并。所以一样的套路,先排序,让所有的相邻区间尽可能的重叠在一起,按左边界,或者右边界排序都可以,处理逻辑稍有不同。

唯一需要考虑的是什么时候更新区间以及添加到ls中。

javascript 复制代码
class Solution {
    public int[][] merge(int[][] intervals) {
        List<int[]> ls = new ArrayList<>();
        if(intervals.length == 1) return intervals;
        Arrays.sort(intervals,(a,b)->Integer.compare(a[0], b[0])); // 按照左边界排序
        int start = intervals[0][0],end = intervals[0][1];
        for(int i = 1;i<intervals.length;i++){
            // 无重叠
            if(intervals[i][0] > end){
                // 合并
                ls.add(new int[]{start,end});
                // 更新
                start = intervals[i][0];
                end = intervals[i][1];
            }
            else{
                end = Math.max(end,intervals[i][1]);
            }
        }
        ls.add(new int[]{start,end});
        return ls.toArray(new int[ls.size()][]);
    }
}
相关推荐
Jerry11 小时前
LeetCode 28. 找出字符串中第一个匹配项的下标
算法
Jerry13 小时前
LeetCode 459. 重复的子字符串
算法
海石16 小时前
1500分的题目,确实有实力,不过还是我略胜一筹
算法·leetcode
海石16 小时前
【记忆化搜索】条条大路通AC,走好适合你的那一条,走到后再考虑走得快
算法·leetcode
Jerry18 小时前
LeetCode 151. 反转字符串中的单词
算法
a11177620 小时前
LM 算法迭代过程动画演示(SLAM)
算法
头茬韭菜20 小时前
Context 的生死抉择:四层压缩、截断算法与 Session Memory
算法·ai
Jerry21 小时前
LeetCode 541. 反转字符串 II
算法
Jerry21 小时前
LeetCode 344. 反转字符串
算法
搞科研的小刘选手21 小时前
【香港大学主办&IEEE出版】第六届计算机视觉、应用与算法国际学术会议(CVAA 2026)
算法·计算机视觉·应用·学术会议