715. Range Module
Hard
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:
[left, right)
denotes all real numbers left <= x < right
.0 < left < right < 10^9
in all calls to addRange, queryRange, removeRange
.addRange
in a single test case is at most 1000
.queryRange
in a single test case is at most 5000
.removeRange
in a single test case is at most 1000
.1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | class RangeModule { TreeMap<Integer, Integer> map = new TreeMap<>(); public RangeModule() { } //remove [l, r] int[] remove(int start, int end){ int l = start, r = end; Map.Entry<Integer, Integer> lEntry = map.floorEntry(l); if(lEntry!=null && lEntry.getValue()>=l){ l = lEntry.getKey(); } Map.Entry<Integer, Integer> rEntry = map.floorEntry(r); if(rEntry!=null && rEntry.getValue()>=r){ r = rEntry.getValue(); } Map<Integer, Integer> submap = map.subMap(l, true, r, true); Set<Integer> set = new HashSet<>(submap.keySet()); map.keySet().removeAll(set); return new int[]{l, r}; } public void addRange(int left, int right) { int[] intv = remove(left, right); map.put(intv[0], intv[1]); } public boolean queryRange(int left, int right) { int l = left; Map.Entry<Integer, Integer> lEntry = map.floorEntry(l); if(lEntry==null) return false; if(lEntry.getValue()>=right) return true; return false; } public void removeRange(int left, int right) { int[] intv = remove(left, right); if(intv[0]<left) map.put(intv[0], left); if(right<intv[1]) map.put(right, intv[1]); } } /** * 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); */ |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 | package MJ0208; /* 给一个乱序数组如 [4 3 7 6 9 2] 定义一个range k, 如果任意两个数之间绝对值的差小于k,这两个数就属于同一数组, 如果a,b同属一组,a,c也同属一组,则b,c也同属一组,最终将小组分类好,返回分类好的组合,比如之前这个例子, 如果k=1 则 result = [[4 3 2],[7 6],[9]],此题不知道蠡口上有没有,如果有的话还请见多识广的大家提供的题号, 我感觉我准备的方法不是面试官期望的最优解,我是现将数组排序,然后检查相邻数字归入一组,如果超出range就新开一组, 但是这次要求保持同一小组内数字原有的相对顺序,所以我还开了一个tuple记录原来的顺序,然后小组内排序,总之感觉整的挺麻烦的。 我这算法的时间复杂度应该是O(nlogn) 空间是O(n) */ import java.util.*; public class Main { public static void main(String[] args) { Solution sol = new Solution(); List<List<Integer>> list = sol.findGroupWithinRangeK(new int[]{4,3,7,6,9,2}, 1); System.out.println(Arrays.toString(list.toArray())); } } class Solution { class Intv{ int left, right; List<Integer> members; Intv(int _l, int _r){ left = _l; right = _r; members = new ArrayList<>(); } } void removeRanges(TreeSet<Intv> groups, int left, int right){ TreeSet<Intv> tmp = new TreeSet<>(); for(Intv intv : groups){ if(intv.right<left && intv.left>right){ tmp.add(intv); } } groups = tmp; } List<List<Integer>> findGroupWithinRangeK(int[] arr, int K){ TreeSet<Intv> groups = new TreeSet<>((a,b)->a.right-b.right);//interval's start point for(int a : arr){ int left = a-K, right = a+K; Intv lIntv = groups.ceiling(new Intv(left, left)); Intv rIntv = groups.ceiling(new Intv(right, right)); if(lIntv!=null){ int newLeft = Math.min(left, lIntv.left); int newRight = right; if(rIntv!=null){ newRight = Math.max(newRight, rIntv.right); } removeRanges(groups, newLeft, newRight); groups.add(new Intv(newLeft, newRight)); }else{ groups.add(new Intv(left, right)); } } for(int a : arr){ Intv intv = groups.ceiling(new Intv(a, a)); intv.members.add(a); } List<List<Integer>> list = new ArrayList<>(); for(Intv intv : groups){ list.add(intv.members); } return list; } } |
No comments:
Post a Comment