zoukankan      html  css  js  c++  java
  • LeetCode435. 无重叠区间

    方法1:动态规划。类似于最长上升子序列问题。 时间复杂度为O(n^2), 空间复杂度:O(n)

        先将所有的 n 个区间按照左端点从小到大进行排序,随后使用动态规划的方法求出区间数量的最大值。

    ☆☆☆☆方法2【最优解】:贪心算法。时间复杂度:O(nlogn), 空间复杂度:O(logn)

        每次选择中,前一个区间的结尾越小,后面越有可能容纳更多区间。

        两种思路,可以对区间尾进行排序,也可以对区间头排序。

    代码1:

    class Solution {
        public int eraseOverlapIntervals(int[][] intervals) {
            if (intervals.length == 0) {
                return 0;
            }
            // 对每个区间排序,以区间头的大小为参考
    //        Arrays.sort(intervals, new Comparator<int[]>() {
    //            @Override
    //            public int compare(int[] o1, int[] o2) {
    //                return o1[0] - o2[0]; // 如果返回正数,说明o1[0] > o2[0],不符合升序,正数类比为true,表示需要调整顺序。
    //            }
    //        });
            Arrays.sort(intervals, (o1, o2) -> o1[0] - o2[0]);
            // 状态的定义: dp[i]表示 从区间0开始,以区间i为最后一个区间,可以选出的区间数量的最大值。
            //      初始化:把区间i单独拿出来就是1个互不重叠的区间,因此初始化为1
            int[] dp = new int[intervals.length];
            Arrays.fill(dp, 1);
            int res = 1;
            for (int i = 1; i < intervals.length; i++) {
                for (int j = 0; j < i; j++) {
                    // 说明区间i可以跟在区间i后面
                    if (intervals[i][0] >= intervals[j][1]) {
                        dp[i] = Math.max(dp[i], 1 + dp[j]);
                    }
                }
                res = Math.max(res, dp[i]); // 所有dp[i]里取最大的
            }
            return intervals.length - res;
        }
    }

    代码2:

    class Solution {
        public int eraseOverlapIntervals(int[][] intervals) {
            if (intervals.length == 0) {
                return 0;
            }
            /**
             * 方法1:按照区间头来排序,记录移除的次数
             *      如果遇到覆盖,那么就需要删除一个区间,因为需要尽可能不与后面的区间产生重叠,
             *      应该让现有区间越短越好,因此需要移除尾部较大的,保留区间结尾较小的。
             */
            Arrays.sort(intervals, (o1, o2) -> o1[0] - o2[0]);
            int count = 0; // 移除的次数
            int pre = 0; // 前一个区间的索引
            for (int i = 1; i < intervals.length; i++) {
                // 如果发生重叠
                if (intervals[i][0] < intervals[pre][1]) {
                    count ++;
                    // 更新保留的区间索引,保留尾部较小的那个
                    pre = intervals[pre][1] < intervals[i][1] ? pre : i;
                }else {
                    pre = i;
                }
            }
            return count;
            /**
             * 方法2:按照区间尾来排序,记录选择区间的个数
             *      每次选择结尾最早的,且和前一个区间不重叠的区间
             */
            /*
            Arrays.sort(intervals, (o1, o2) -> o1[1] - o2[1]);
            int res = 1; // 选择区间的个数
            int pre = 0;
            for (int i = 1; i < intervals.length; i++) {
                if (intervals[i][0] >= intervals[pre][1]) {
                    res ++;
                    pre = i;
                }
            }
            return intervals.length - res;
            */
        }
    }

    【知识点补充】如何自定义排序规则为 升序 还是 降序

      设o1表示位于前面的元素,o2表示后面的元素。

      如果想升序,对于o1-o2,如果结果为负数,说明o1 < o2,符合升序要求,负数类比为false,表示不需要调整顺序。

                   如果结果为正数,说明o1 > o2,不符合升序要求,正数类比为true,表示需要调整顺序。

      如果想降序,对于o2-o1,如果结果为负数,说明o2 < o1,符合降序要求,负数类比为false,表示不需要调整顺序。

                   如果结果为正数,说明o2 > o1,不符合降序要求,正数类比为true,表示需要调整顺序。

  • 相关阅读:
    正则表达式把所有Paul替换成Ringo:Paul Puala Pualine paul Paul
    DOM 和 BOM
    新手的grid布局
    css中的单位和css中的颜色表示方法
    css定位
    Winform 通过 WebBrowser 与 JS 交互
    PDF目录编辑器使用介绍
    [.NET] 控制只启动单个指定外部程序
    搭建 Frp 来远程内网 Windows 和 Linux 机子
    CentOs8 nmcli命令行方式操作网卡配置
  • 原文地址:https://www.cnblogs.com/HuangYJ/p/14232874.html
Copyright © 2011-2022 走看看