zoukankan      html  css  js  c++  java
  • [LeetCode 715] Range Module

    A Range Module is a module that tracks ranges of numbers. Your task is to design and implement the following interfaces in an efficient manner.

     

    • addRange(int left, int right) Adds the half-open interval [left, right), tracking every real number in that interval. Adding an interval that partially overlaps with currently tracked numbers should add any numbers in the interval [left, right) that are not already tracked. 
    • queryRange(int left, int right) Returns true if and only if every real number in the interval [left, right) is currently being tracked.
    • removeRange(int left, int right) Stops tracking every real number currently being tracked in the interval [left, right).

     

    Example 1:

    addRange(10, 20): null
    removeRange(14, 16): null
    queryRange(10, 14): true (Every number in [10, 14) is being tracked)
    queryRange(13, 15): false (Numbers like 14, 14.03, 14.17 in [13, 15) are not being tracked)
    queryRange(16, 17): true (The number 16 in [16, 17) is still being tracked, despite the remove operation)
    

     

    Note:

    • A half open interval [left, right) denotes all real numbers left <= x < right.
    • 0 < left < right < 10^9 in all calls to addRange, queryRange, removeRange.
    • The total number of calls to addRange in a single test case is at most 1000.
    • The total number of calls to queryRange in a single test case is at most 5000.
    • The total number of calls to removeRange in a single test case is at most 1000.

    Solution 1.  Use TreeMap to maintain a sorted set of disjoint intervals. 

    Create a tree map. Each entry represents an interval, key is the start number and value is the end number. 

    1. queryRange(left, right): find the rightmost entry whose start number is <= left; if existing, check if it covers [left, right - 1];  floorEntry

    2. addRange(left, right):  find the rightmost entry e whose start number is <= left; if null or this entry does not intersect with [left, right - 1], i.e: e.getValue() < left, or not adjacent to left, i.e, e.getValue() < left - 1, we need to get the next entry by calling higherEntry on key left to get the first entry that needs to be updated. 

    Keep two variables start and end, for each intersecting or adjacent entry, update start and end, remove the current entry then move on to the next higher entry and repeat until there are no ntersecting or adjacent entries. Then insert enrty(start, end) to map.

    3. removeRange(left, right):  Similar with addRange except that we do not need to check if entries are adjacent to [left, right - 1] anymore. For removal, we only care about intersecting entries. For each intersecting entry e, after removing it from the map, check e.getKey() vs left - 1, right vs e.getValue(). If they still form valid range, insert them back to the map. 

    class RangeModule {
        private TreeMap<Integer, Integer> map;
        public RangeModule() {
            map = new TreeMap<>();
        }
        
        public void addRange(int left, int right) {
            Map.Entry<Integer, Integer> e = map.floorEntry(left);
            int start = left, end = right - 1;
            if(e == null || e.getValue() < left - 1) {
                e = map.higherEntry(left);
            }
            while(e != null && e.getKey() - 1 <= right - 1) {
                Map.Entry<Integer, Integer> next = map.higherEntry(e.getKey());
                start = Math.min(start, e.getKey());
                end = Math.max(end, e.getValue());
                map.remove(e.getKey());
                e = next;
            }
            map.put(start, end);
        }
        
        public boolean queryRange(int left, int right) {
            Map.Entry<Integer, Integer> e = map.floorEntry(left);
            if(e == null) return false;
            return right - 1 <= e.getValue();
        }
        
        public void removeRange(int left, int right) {
            Map.Entry<Integer, Integer> e = map.floorEntry(left);
            if(e == null || e.getValue() < left) {
                e = map.higherEntry(left);
            }
            while(e != null && e.getKey() <= right - 1) {
                Map.Entry<Integer, Integer> next = map.higherEntry(e.getKey());
                int l1 = e.getKey(), r1 = left - 1;
                int l2 = right, r2 = e.getValue();
                map.remove(e.getKey());
                if(l1 <= r1) {
                    map.put(l1, r1);
                }
                if(l2 <= r2) {
                    map.put(l2, r2);
                }
                e = next;
            } 
        }
    }
    
    /**
     * Your RangeModule object will be instantiated and called as such:
     * RangeModule obj = new RangeModule();
     * obj.addRange(left,right);
     * boolean param_2 = obj.queryRange(left,right);
     * obj.removeRange(left,right);
     */

    This problem is also tagged as segment tree. But I have not came up with an easy solution that uses segment tree.

     
  • 相关阅读:
    TdxGaugeControl
    TdxSkinController
    delphi TdxMemData 使用
    深入方法(16)- 方法的顺序
    深入方法(15)- 调用其他单元的函数
    深入方法(14)- 在TForm1 类内声明的方法
    深入方法(13)- 在 interface 区声明的方法
    深入方法(12)- implementation 区中的方法
    深入方法(11)- 参数前缀
    深入方法(10)- 默认参数
  • 原文地址:https://www.cnblogs.com/lz87/p/14381206.html
Copyright © 2011-2022 走看看