Data Stream as Disjoint Intervals
Hard
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]
思路
维护一个有序数组存储所有interval,interval的左边界和右边界存在同一个数组中。插入新的元素时二分查找元素应该插入的位置,注意讨论各种边界情况。
代码
/*
* @lc app=leetcode id=352 lang=java
*
* [352] Data Stream as Disjoint Intervals
*/
class SummaryRanges {
List<Integer> ranges = new ArrayList<Integer>();
public int[][] toArrays() {
int i = 0, n = ranges.size()/2;
int[][] ret = new int[n][2];
for (i=0; i<n; ++i) {
ret[i][0] = ranges.get(2*i);
ret[i][1] = ranges.get(2*i+1);
}
return ret;
}
/**
* find the first element position >= target
*/
private int binarySearch(int target) {
int n = ranges.size(), l = 0, r = n-1, m = 0;
if (target > ranges.get(n-1)) {
return n;
}
if (target <= ranges.get(0)) {
return 0;
}
while (l < r) {
m = (l + r) / 2;
if (ranges.get(m) < target) {
l = m + 1;
} else {
r = m;
}
}
return l;
}
/** Initialize your data structure here. */
public SummaryRanges() {
}
public void addNum(int val) {
int n = ranges.size();
if (n == 0) {
ranges.add(val);
ranges.add(val);
return;
}
int idx = binarySearch(val);
if ((idx & 1) == 0) { // between intervals
if (idx < n && val == ranges.get(idx)) {
return;
}
if (idx == n) {
if (val == ranges.get(n-1) + 1) {
ranges.set(n-1, val);
} else {
ranges.add(val);
ranges.add(val);
}
} else if (idx == 0) {
if (val == ranges.get(idx) - 1) {
ranges.set(0, val);
} else {
ranges.add(0, val);
ranges.add(0, val);
}
} else {
if (val == ranges.get(idx) - 1 && val == ranges.get(idx-1) + 1) {
ranges.remove(idx-1);
ranges.remove(idx-1);
} else if (val == ranges.get(idx) - 1) {
ranges.set(idx, val);
} else if (val == ranges.get(idx-1) + 1) {
ranges.set(idx-1, val);
} else {
ranges.add(idx, val);
ranges.add(idx, val);
}
}
}
return;
}
public int[][] getIntervals() {
return toArrays();
}
}
/**
* Your SummaryRanges object will be instantiated and called as such:
* SummaryRanges obj = new SummaryRanges();
* obj.addNum(val);
* int[][] param_2 = obj.getIntervals();
*/