zoukankan      html  css  js  c++  java
  • 力扣452题、435题、56题(用最少量的箭引爆气球,无重叠区间,合并区间)

    452、用最少量的箭引爆气球

    基本思想:

    贪心

    具体实现:

    局部最优:当气球出现重叠,射,所用弓箭最少

    全局最优:把所有气球射爆

    1.为了让气球更好的重叠,需要对气球数组进行排序

       按照起始位置进行排序,从前向后遍历数组,靠左尽可能让气球重复

    2.气球重叠后,重叠气球中右边边界的最小值之前的区间需要一个弓箭

    3.气球1,2需要一个弓箭,

    气球3的左边界大于了第一组重叠气球的最小右边界,所以气球3需要另一支箭

    4.题目中说满足 xstart ≤ x ≤ xend,则该气球会被引爆。

    说明两个气球挨在一起不重叠也可以一起射爆,所以代码中 if (points[i][0] > points[i - 1][1]) 不能是>=

    代码:

    class Solution {
        public int findMinArrowShots(int[][] points) {
            if (points.length == 0) return 0;
            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;
        }
    }

    435、无重叠区间

    基本思想:

    贪心算法

    具体实现:

    1.按照右边界排序,就从左向右遍历

    2.从左向右记录非交叉区间的个数

    3.区间总数 - 非交叉区间的个数 = 要移除区间的个数

    局部最优:因为按右边界排序的,从左向右遍历的话可以优先选右边界小的区间,

                          留给下一个区间的空间大一些,可以更容易避免交叉

    全局最优:选取最多的非交叉区间

    1. 区间1,2,3,4,5,6按照右边界排好序

    每次找没有交叉的区间是,用右边界最小的来找,这样留给下一个区间的空间就越大,

    第一条分割线就是区间1结束的位置

    2.再找和区间1没有交叉的区间,选择区间4

        区间5和区间1也没有交叉,但是区间4的右边界小于区间5,所以选择区间4,而且是按右边界小的顺序来遍历的

    3.接下来找到区间6

    4.有3个没有交叉的区间

    5.总区间-没有交叉的区间

    代码:

    class Solution {
        public int eraseOverlapIntervals(int[][] intervals) {
            if (intervals.length < 2) return 0;
            Arrays.sort(intervals, new Comparator<int[]>(){
                public int compare(int[] o1, int[] o2){
                    if (o1[1] != o2[1]){
                        return Integer.compare(o1[1], o2[1]);
                    } else {
                        return Integer.compare(o1[0], o2[0]);
                    }
                }
            });
    
            int count = 1;
            int edge = intervals[0][1];
            for (int i = 1; i < intervals.length; i++){
                if (edge <= intervals[i][0]){
                    count++;
                    edge = intervals[i][1];
                }
            }
            return intervals.length - count;
        }
    }

    56、合并区间

    基本思想:

    贪心

    具体实现:

    1.按照左边界排序

    2.局部最优:每次合并取最大的右边界,这样可以合并更多的区间

    3.整体最优:合并所有重叠的区间

    代码:

    class Solution {
        public int[][] merge(int[][] intervals) {
            List<int[]> res = new LinkedList<>();
            Arrays.sort(intervals, (o1, o2) -> Integer.compare(o1[0], o2[0]));
    
            int start = intervals[0][0];
            for (int i = 1; i < intervals.length; i++){
                //如果当前左边界大于上一个右边界,说明没有重合
                if (intervals[i][0] > intervals[i-1][1]) {
                    //就把靠左的这个和别人没重合的区间加入结果数组
                    res.add(new int[]{start, intervals[i - 1][1]});
                    //更新start为靠右的这个区间的左边界
                    start = intervals[i][0];
                //这两个区间重合了 
                } else {
                    //取当前区间右边界和上一个区间的右边界的最大值
                    intervals[i][1] = Math.max(intervals[i][1], intervals[i-1][1]);
                }
            }
            res.add(new int[]{start, intervals[intervals.length - 1][1]});
            return res.toArray(new int[res.size()][]);
        }
    }
  • 相关阅读:
    经典的笔试题python操作数据库和python设计模式【多测师_王sir】
    上证所python笔试题【多测师_王sir】
    银行移动消费信贷业务梳理【多测师_王sir】
    查看log.txt 日志文件中包含关键字x123或者x124的行,以及该行前后10行内容,并输出到out.txt中【多测师_王sir】【Linux题目】
    文件权限设置
    windows OpenSSH WARNING: UNPROTECTED PRIVATE KEY FILE!
    vue对象合并
    elk安装配置
    ElasticSearch
    Elastic Search之Search API(Query DSL)、字段类查询、复合查询
  • 原文地址:https://www.cnblogs.com/zhaojiayu/p/15449608.html
Copyright © 2011-2022 走看看