zoukankan      html  css  js  c++  java
  • Interval 间隔问题

    2018-09-07 09:03:14

    一、Merge Intervals

    问题描述:

    问题求解:

        public List<Interval> merge(List<Interval> intervals) {
            List<Interval> res = new ArrayList<>();
            if (intervals.size() == 0) return res;
            Collections.sort(intervals, new Comparator<Interval>() {
                public int compare(Interval o1, Interval o2) {
                    return o1.start - o2.start;
                }
            });
            int start = intervals.get(0).start;
            int end = intervals.get(0).end;
            for (int i = 1; i < intervals.size(); i++) {
                if (intervals.get(i).start > end) {
                    res.add(new Interval(start, end));
                    start = intervals.get(i).start;
                    end = intervals.get(i).end;
                }
                else {
                    end = Math.max(end, intervals.get(i).end);
                }
            }
            res.add(new Interval(start, end));
            return res;
        }
    

    二、Insert Interval

    问题描述:

    问题求解:

    本题的问题描述中明确的说明了,本题的给出条件中的intervals是已经排序好的,并且是没有overlapping的,因此在后续的求解过程中只需要一次遍历即可。

        public List<Interval> insert(List<Interval> intervals, Interval newInterval) {
            List<Interval> res = new ArrayList<>();
            int i = 0;
            while (i < intervals.size() && intervals.get(i).end < newInterval.start) {
                res.add(intervals.get(i++));
            }
            while (i < intervals.size() && intervals.get(i).start <= newInterval.end) {
                newInterval.start = Math.min(newInterval.start, intervals.get(i).start);
                newInterval.end = Math.max(newInterval.end, intervals.get(i).end);
                i++;
            }
            res.add(newInterval);
            while (i < intervals.size()) res.add(intervals.get(i++));
            return res;
        }
    

    三、My Calendar I

    问题描述:

    问题求解:

    解法一:Boundary Counting

    对边界进行计数,最后遍历一遍即可,如果过程中有curSum大于1的情况,则表明出现了overlapping。

    如果使用keySet()则会多出log(n)的时间,而本题卡时间非常紧,如果使用key进行提取,则会TLE。

    如果使用entrySet(),则会Accept,但是也是将将通过。

    public class MyCalendar {   
      TreeMap<Integer, Integer> map;

        public MyCalendar() {
            map = new TreeMap<>();
        }
        
        public boolean book(int start, int end) {
            return helper(start, end);
        }
        
        private boolean helper(int start, int end) {
            map.put(start, map.getOrDefault(start, 0) + 1);
            map.put(end, map.getOrDefault(end, 0) - 1);
            int curSum = 0;
            for (Map.Entry<Integer, Integer> entry : map.entrySet()) {
                curSum += entry.getValue();
                if (curSum > 1) {
                    map.put(start, map.get(start) - 1);
                    if (map.get(start) == 0) map.remove(start);
                    map.put(end, map.get(end) + 1);
                    if (map.get(end) == 0) map.remove(end);
                    return false;
                }
            }
            return true;
        }
    }

    解法二、

    记录各个interval,并且所有的interval都是没有overlapping的。

    public class MyCalendar {      
      TreeMap<Integer, Integer> treeMap; public MyCalendar() { treeMap = new TreeMap<>(); } public boolean book(int start, int end) { Integer floor = treeMap.floorKey(start); if (floor != null && treeMap.get(floor) > start) return false; Integer ceil = treeMap.ceilingKey(start); if (ceil != null && ceil < end) return false; treeMap.put(start, end); return true; }
    }

    四、My Calendar II

    问题描述:

    问题求解:

    万能的Boundary Counting。

    public class MyCalendarTwo {
        TreeMap<Integer, Integer> map;
    
        public MyCalendarTwo() {
            map = new TreeMap<>();
        }
    
        public boolean book(int start, int end) {
            map.put(start, map.getOrDefault(start, 0) + 1);
            map.put(end, map.getOrDefault(end, 0) - 1);
            int cnt = 0;
            for (Map.Entry<Integer, Integer> entry : map.entrySet()) {
                cnt += entry.getValue();
                if (cnt > 2) {
                    map.put(start, map.get(start) - 1);
                    if (map.get(start) == 0) map.remove(start);
                    map.put(end, map.get(end) + 1);
                    if (map.get(end) == 0) map.remove(end);
                    return false;
                }
            }
            return true;
        }
    }
    

    五、My Calendar III

    问题描述:

    问题求解:

    解法一:

    万能的Boundary Counting。

    public class MyCalendarThree {
        TreeMap<Integer, Integer> map;
    
        public MyCalendarThree() {
            map = new TreeMap<>();
        }
    
        public int book(int start, int end) {
            map.put(start, map.getOrDefault(start, 0) + 1);
            map.put(end, map.getOrDefault(end, 0) - 1);
            int res = 0;
            int cnt = 0;
            for (Map.Entry<Integer, Integer> entry : map.entrySet()) {
                cnt += entry.getValue();
                if (res < cnt) res = cnt;
            }
            return res;
        }
    }
    

    解法二:

    线段树求解,效率有较大的提升。

    public class MyCalendarThree {
        SegmentTree root;
        int res;
    
        public MyCalendarThree() {
            root = new SegmentTree(0, 1000000000, 0);
            res = 0;
        }
    
        public int book(int start, int end) {
            add(start, end, root);
            return res;
        }
    
        private void add(int start, int end, SegmentTree root) {
            if (root.m != -1) {
                if (start >= root.m) add(start, end, root.right);
                else if (end <= root.m) add(start, end, root.left);
                else {
                    add(start, root.m, root.left);
                    add(root.m, end, root.right);
                }
                return;
            }
    
            if (start == root.l && end == root.r) {
                root.cnt++;
                res = Math.max(res, root.cnt);
            }
            else if (start == root.l) {
                root.m = end;
                root.left = new SegmentTree(start, root.m, root.cnt + 1);
                root.right = new SegmentTree(root.m, root.r, root.cnt);
                res = Math.max(res, root.cnt + 1);
            }
            else if (end == root.r) {
                root.m = start;
                root.left = new SegmentTree(root.l, root.m, root.cnt);
                root.right = new SegmentTree(root.m, root.r, root.cnt + 1);
                res = Math.max(res, root.cnt + 1);
            }
            else {
                root.m = start;
                root.left = new SegmentTree(root.l, root.m, root.cnt);
                root.right = new SegmentTree(root.m, root.r, root.cnt);
                add(start, end, root.right);
            }
        }
    }
    
    class SegmentTree {
        int l;
        int r;
        int m; // m : 分割点,如果尚未分割则为-1。
        int cnt;
        SegmentTree left;
        SegmentTree right;
    
        SegmentTree(int l, int r, int cnt) {
            this.l = l;
            this.r = r;
            this.m = -1;
            this.cnt = cnt;
            this.left = null;
            this.right = null;
        }
    }
    

    六、Interval List Intersections

    问题描述:

    问题求解:

    如何快速判断是否相交呢?

        public int[][] intervalIntersection(int[][] A, int[][] B) {
            List<int[]> res = new ArrayList<>();
            int i = 0;
            int j = 0;
            while (i < A.length && j < B.length) {
                int s = Math.max(A[i][0], B[j][0]);
                int e = Math.min(A[i][1], B[j][1]);
                if (s <= e) res.add(new int[]{s, e});
                if (A[i][1] < B[j][1]) i++;
                else j++;
            }
            int[][] rst = new int[res.size()][2];
            for (i = 0; i < res.size(); i++) {
                rst[i][0] = res.get(i)[0]; 
                rst[i][1] = res.get(i)[1];
            }
            return rst;
        }
    

      

      

  • 相关阅读:
    【Leetcode】【hard】Binary Tree Postorder Traversal
    【Leetcode】【Easy】Contains Duplicate
    【Leetcode】【Easy】Isomorphic Strings
    【Leetcode】【Medium】Simplify Path
    【Leetcode】【Medium】Add Two Numbers
    【Leetcode】【Hard】Copy List with Random Pointer
    安装torch-opencv
    【转】ubuntu下修改文件夹权限
    Lua 中的 function、closure、upvalue
    多目标跟踪方法 NOMT 学习与总结
  • 原文地址:https://www.cnblogs.com/hyserendipity/p/9602549.html
Copyright © 2011-2022 走看看