LeetCode-Data Stream as Disjoint Intervals

LiBlog發表於2016-07-20

Given a data stream input of non-negative integers a1, a2, ..., an, ..., summarize the numbers seen so far as a list of disjoint intervals.

For example, suppose the integers from the data stream are 1, 3, 7, 2, 6, ..., then the summary will be:

[1, 1]
[1, 1], [3, 3]
[1, 1], [3, 3], [7, 7]
[1, 3], [7, 7]
[1, 3], [6, 7]

Follow up:
What if there are lots of merges and the number of disjoint intervals are small compared to the data stream's size?

Credits:
Special thanks to @yunhong for adding this problem and creating most of the test cases.

 

Solution 1:

 1 /**
 2  * Definition for an interval.
 3  * public class Interval {
 4  *     int start;
 5  *     int end;
 6  *     Interval() { start = 0; end = 0; }
 7  *     Interval(int s, int e) { start = s; end = e; }
 8  * }
 9  */
10 public class SummaryRanges {
11 
12    /** Initialize your data structure here. */
13         public SummaryRanges() {
14             startMap = new HashMap<Integer, Interval>();
15             endMap = new HashMap<Integer, Interval>();
16             addedNum = new HashSet<Integer>();
17         }
18 
19         public void addNum(int val) {
20             if (addedNum.contains(val)) return;
21             
22             Interval pre = null, after = null;
23             if (endMap.containsKey(val - 1))
24                 pre = endMap.get(val - 1);
25             if (startMap.containsKey(val + 1))
26                 after = startMap.get(val + 1);
27 
28             if (pre != null && after != null) {
29                 endMap.remove(after.end);                
30                 startMap.remove(after.start);
31                 endMap.remove(pre.end);
32                 pre.end = after.end;
33                 endMap.put(pre.end, pre);
34             } else if (pre != null) {
35                 endMap.remove(pre.end);
36                 pre.end = val;
37                 endMap.put(val, pre);
38             } else if (after != null) {
39                 startMap.remove(after.start);
40                 after.start = val;
41                 startMap.put(val, after);
42             } else {
43                 Interval single = new Interval(val, val);
44                 endMap.put(val, single);
45                 startMap.put(val, single);
46             }
47             
48             addedNum.add(val);
49         }
50 
51         public List<Interval> getIntervals() {
52             List<Interval> intervalList = new ArrayList<Interval>(endMap.values());
53             Collections.sort(intervalList, new Comparator<Interval>() {
54                 public int compare(Interval v1, Interval v2) {
55                     return v1.start - v2.start;
56                 }
57             });
58             return intervalList;
59         }
60 
61         HashMap<Integer, Interval> startMap;
62         HashMap<Integer, Interval> endMap;
63         HashSet<Integer> addedNum;
64 }
65 
66 /**
67  * Your SummaryRanges object will be instantiated and called as such:
68  * SummaryRanges obj = new SummaryRanges();
69  * obj.addNum(val);
70  * List<Interval> param_2 = obj.getIntervals();
71  */

This solution introduces many redundant: To find the "pre", we only need to find the interval with the largest start that is less than val. In short, we only need to compare Interval.start

Solution 2:

 1 /**
 2  * Definition for an interval.
 3  * public class Interval {
 4  *     int start;
 5  *     int end;
 6  *     Interval() { start = 0; end = 0; }
 7  *     Interval(int s, int e) { start = s; end = e; }
 8  * }
 9  */
10 public class SummaryRanges {
11 
12     /** Initialize your data structure here. */
13     public SummaryRanges() {
14         itvlSet = new TreeSet<Interval>(new Comparator<Interval>(){
15             public int compare(Interval v1, Interval v2){
16                 return v1.start-v2.start;
17             }
18         });
19         
20     }
21     
22     public void addNum(int val) {
23         Interval itvl = new Interval(val,val);
24         Interval pre = itvlSet.floor(itvl);
25         Interval after = itvlSet.ceiling(itvl);
26         
27         if ( (pre!=null && pre.end >= val) || (after!=null && after.start <=val)) return;
28         
29         if (pre!=null && pre.end==val-1){
30             itvlSet.remove(pre);
31             itvl.start = pre.start;
32         }
33         if (after!=null && after.start==val+1){
34             itvlSet.remove(after);
35             itvl.end = after.end;
36         }
37         itvlSet.add(itvl);
38     }
39     
40     public List<Interval> getIntervals() {
41         return new ArrayList<Interval>(itvlSet);
42         
43     }
44     
45     TreeSet<Interval> itvlSet;
46 }
47 
48 /**
49  * Your SummaryRanges object will be instantiated and called as such:
50  * SummaryRanges obj = new SummaryRanges();
51  * obj.addNum(val);
52  * List<Interval> param_2 = obj.getIntervals();
53  */