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.

     
  • 相关阅读:
    列“XAxisBacklas”不属于表 Table。
    无经意中收看了《微软英雄》片段
    书编程(Asp.net)
    Runtime Error
    书编程(其他)
    书英语书
    【转】CodeBlocks中文版使用手册
    Java关键字this、super使用总结(转)
    分析对比主流Bootloader的性能
    C语言指针的初始化和赋值
  • 原文地址:https://www.cnblogs.com/lz87/p/14381206.html
Copyright © 2011-2022 走看看