给定许多区间[ai, bi],找到与最多数量的区间相交的区间。我们能以O(nlogn)或更快的速度完成吗?我只能想到一个n^2的方法。
给定许多区间[ai, bi],找到与最多数量的区间相交的区间。我们能以O(nlogn)或更快的速度完成吗?我只能想到一个n^2的方法。
(a1,b1), ..., (an,bn)
,制作一个长度为2n
的排序数组,其中通过以下方式解决平局:
ai = aj
,则当且仅当 bi < bj
时,先将 ai
排在前面。bi = bj
,则当且仅当 ai < aj
时,先将 bi
排在前面。ai = bj
,则先将 ai
排在前面。a
或 b
(可以使用长度为2n
的二进制数组来完成此操作)。遍历数组,并跟踪与给定点相交的区间数(即 a
的累加和减去 b
的累加和)。在最大重叠的区间发生的地方,遇到的最大数字即为最大相交数量。O(n log n)
。(a1,b1),(a2,b2),(a3,b3) = (1,2),(1,3),(2,4)
,那么排序后的顺序是 a2,a1,b1,a3,b2,b3
。 - PengOne1) Construct two n arrays, one is sort by ai, another is sort by bi.
make sure that if ai==aj, then bi<bj, but i before j, the same as b-array.
2) Walk through the b-array for each b, Do a binary search in a-array to find
index, make sure a[index]<=b<a[index+1]
3) find the max(index - i + 1), the the bi is the point we need.
代码
public int getPoint(List<Interval> intervals) {
// validation
if (intervals == null || intervals.size() == 0) {
return 0;
}
List<Interval> sortA = sortByA(intervals);
List<Interval> sortB = sortByB(intervals);
int max = 0;
int maxPoint = sortB.get(0).b;
for (int i = 0; i < sortB.size(); i++) {
Interval interval = sortB.get(i);
// find B in sortA.
int index = search(sortA, interval.b);
int count = index - i + 1;
if (count > max) {
max = count;
maxPoint = sortB.get(i).b;
}
}
return maxPoint;
}
聚合:
for (int i = 1; i <= N; i++) { sum[i] += sum[i - 1]; }
//这是一个O(N)的步骤。
这个区间[ai, bi]是一个解决方案,它与所有其他区间相交的次数为“sum[k] - 1”(不计算它本身)。
如果ai,bi是小整数(例如16位数字),则一种替代区间树的方法是:
迭代j时的x值给出与点j相交的区间数量,因此找到最大值可以得到相交最多的点。
这需要O(N+n)个周期,因此仅在n>N的情况下对您的应用程序有用。
(严格来说,这并没有回答问题,因为它找到了相交最多的点。但是,您应该能够扩展此方法以找到相交最多的区间。)
你可以在n中完成它。
[最小的ai,最大的bi]
所以。。。
varmin = interval[0]['begin']
varmax = interval[0]['end']
foreach( interval as rang ) {
varmin = min( rang['begin'], varmin )
varmax = max( rang['end'], varmax ) }
newrange = array('begin'=>varmin,'end'=>varmax)