老师Java动态规划解法貌似超时了

来源:10-2 贪心算法与动态规划的关系 Non-overlapping Intervals

湿地车手

2021-10-24

还有老师,为什么按照起始位置排序以后就能动态规划求出最长子序列了呢?隐隐约约好像是这样的,但是老是想不清楚。

class Solution {
    public static class Interval {
        int start;
        int end;
        Interval() { start = 0; end = 0; }
        Interval(int s, int e) { start = s; end = e; }
    }
    // 相当于求最长上升子序列,再剪一剪
    public int eraseOverlapIntervals(int[][] intervals) {
        if(intervals.length == 1) return 0;
        Interval[] ranges = new Interval[intervals.length];
        int totalLen = intervals.length;
        for(int i = 0; i < totalLen; i++) {
            ranges[i] = new Interval(intervals[i][0], intervals[i][1]);
        }
        Arrays.sort(ranges, new Comparator<Interval>() {
            @Override
            public int compare(Interval o1, Interval o2) {
                if(o1.start != o2.start)
                    return o1.start - o2.start;
                return o1.end - o2.end;
            }
        });
        int[] memo = new int[intervals.length];
        Arrays.fill(memo, -1);
        int max = 1;
        for(int i = 0; i < totalLen; i++) {
            max = Math.max(max, tryFindMax(i, ranges, memo));
        }
        return totalLen - max;
    }
    // 寻找从 index 开始(必选)的最长上升子序列
    private int tryFindMax(int index, Interval[] intervals, int[] memo) {
        if(index >= intervals.length) return 0;
        if(memo[index] != -1) return memo[index];
        int max = 1;
        for(int next = index + 1; next < intervals.length; next++) {
            int curR = intervals[index].end;
            int nextL = intervals[next].start;
            if(nextL < curR) {
                continue;
            } else {
                max = Math.max(max, 1 + tryFindMax(next, intervals, memo));
            }
        }
        return memo[index] = max;
    }
}

跟老师思路一样,就是换成了递归写法,迭代写法一样超时试了一下

写回答

1回答

liuyubobobo

2021-10-25

这是第几号问题?


==========


这个问题新加了测试用例,O(n^2) 的动态规划已经过不了了。需要使用 O(nlogn) 的贪心算法。方法是:首先,把每个线段按照结束时间排序。先取结束时间最早的,再取剩下的时间段里结束时间最早的,依次类推。我的参考代码:https://github.com/liuyubobobo/Play-Leetcode/blob/master/0001-0500/0435-Non-overlapping-Intervals/cpp-0435/main4.cpp


可以思考一下为什么用结束时间排序,可以这样贪心得到解?提示:反证法。


==========


为什么动态规划按照起始时间排序也可以得到解?首先不排序肯定不行。反例随便举:[3, 4] [1, 2]


在排好序以后,我们保证了后一个时间段的起始时间肯定晚于前一个时间段。而在这重循环中:for(int next = index + 1; next < intervals.length; next++)

我们相当于枚举了每一个时间段是否取用。排序保证了不会漏,枚举的过程寻找了最优解。


继续加油!:)

0
4
湿地车手
回复
liuyubobobo
大陆地区。。。主要对自己实在没啥信心。。。明年就要秋招了但是真的感觉菜的扣脚>...<,想尽力冲后端,就怕万一真的找不到工作了不知道客户端能不能算个退路(偶然间知道了字节等公司好像现在在招零基础的客户端),不过还是谢谢老师的鼓励,转专业的感觉知识欠缺的太多了
2021-10-30
共4条回复

玩转算法面试-- Leetcode真题分门别类讲解

课程配套大量BAT面试真题,高频算法题解析,强化训练

7410 学习 · 1150 问题

查看课程