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.

     
  • 相关阅读:
    使用电脑模拟微信内置浏览器
    手机QQ浏览器属于代理服务器吗?
    艾伟:[你必须知道的.NET]第三十二回,深入.NET 4.0之,Tuple一二 狼人:
    艾伟:Silverlight 2.0在IE6 SP2上的虚线边框问题 狼人:
    艾伟:ASP.NET安全问题--Forms验证(后篇)--实战篇 狼人:
    艾伟:基于.NET平台的Windows编程实战(四)—— 数据库操作类的编写 狼人:
    艾伟:WMGPS开发 狼人:
    艾伟:基于.NET平台的Windows编程实战(一)——前言 狼人:
    艾伟:.NET,你忘记了么?(八) 从dynamic到特性误用 狼人:
    艾伟:小巧优美的ORM框架doodads入门指南[转载] 狼人:
  • 原文地址:https://www.cnblogs.com/lz87/p/14381206.html
Copyright © 2011-2022 走看看