352. Data Stream as Disjoint Intervals
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?
class SummaryRanges { // PriorityQueue<Integer> pq; List<Integer> list; /** Initialize your data structure here. */ public SummaryRanges() { // pq = new PriorityQueue<>(); list = new ArrayList(); } public void addNum(int val) { // pq.offer(val); if(list.indexOf(val) < 0) list.add(val); Collections.sort(list); // for(int i = 0; i < list.size(); i++) { // } } public int[][] getIntervals() { // System.out.println(list.toString()); List<int[]> res = new ArrayList(); for(int i = 0; i < list.size(); i++) { int cur = i; while(cur+1 < list.size() && list.get(cur+1) - list.get(cur) == 1) cur++; if(cur != i) res.add(new int[]{list.get(i), list.get(cur)}); else res.add(new int[]{list.get(i), list.get(i)}); i = cur; } int[][] result = new int[res.size()][2]; int j = 0; for(int[] tmp: res) result[j++] = tmp; return result; } } /** * Your SummaryRanges object will be instantiated and called as such: * SummaryRanges obj = new SummaryRanges(); * obj.addNum(val); * int[][] param_2 = obj.getIntervals(); */
1. first ver
Used an arraylist to store unique values, sort after every add. Then generate interval array step by step.
class SummaryRanges { List<int[]> intervals; public SummaryRanges() { this.intervals = new ArrayList<>(); } public void addNum(int val) { // flag: if there is an interval for val boolean noInterval = true; for (int i = 0; i < this.intervals.size(); i++){ // if there is an overlap, break the loop and do nothing if (intervals.get(i)[0] <= val && intervals.get(i)[1] >= val){ noInterval = false; break; } // change the interval; [1,2], val = 3 -> [1,3] if (intervals.get(i)[1] + 1 == val){ intervals.get(i)[1] = val; noInterval = false; } // change the interval; [2,4], val = 3 -> [3,4] if (intervals.get(i)[0] - 1 == val){ intervals.get(i)[0] = val; noInterval = false; } // check if we should merge two intervals; [1,3], [3,4] - > [1,4] if (i != 0 && intervals.get(i - 1)[1] == intervals.get(i)[0]){ intervals.get(i)[0] = intervals.get(i - 1)[0]; intervals.get(i)[1] = intervals.get(i)[1]; intervals.remove(i - 1); } } // if there isnt an interval for val, add to the list. if (noInterval){ intervals.add(new int[]{val, val}); } } public int[][] getIntervals() { Collections.sort(intervals, (a, b) -> a[0]- b[0]); return intervals.toArray(new int[intervals.size()][]); } } /** * Your SummaryRanges object will be instantiated and called as such: * SummaryRanges obj = new SummaryRanges(); * obj.addNum(val); * int[][] param_2 = obj.getIntervals(); */
2.总结:
we just need to consider all situations, firstly we used the arraylist to store intervals.
In every add operation, we checked all situations:
1. no overlap, which is intervals.get[i][0] <= val <= get(i)[1]
2. [1,1], val = 2 whichi is intervals.get(i)[1] + 1 = val, we set intervals.get(i)[1] += 1 ---> [1, 2]
3. [3, 3], val = 2, intervals.get(i)[0] - 1 = val, set intervals.get(i)[0] -= 1 ----> [2, 3]
4. merge neighbor intervals, i != 0 && intervals.get(i - 1)[1] == intervals.get(i)[0], set intervals.get(i)[0] = intervals.get(i-1)[0], and remove i in map
in getIntervals, sort each interval by it's first value and get the result.