当我遇到这个问题时,我使用了一个排序后的范围数组和二分查找来寻找交集。我相信这是O(log n)的性能,但需要一些额外的开销来处理重叠的范围。
你的问题的答案,我认为可以从下面的代码中推导出来,但不包括插入操作。我提供整个代码以避免上下文的混淆 - 我需要将Unicode码点范围插入到码点范围列表中。
--编辑--
将下面的代码调整为确定多个范围的交集,只需从插入点开始进行微不足道的前向搜索,直到找到不再相交的范围即可。
--结束编辑--
Range类包含:
final int lower;
final int upper;
public int compareTo(Object obj) {
if(obj==null) { return -1; }
Range oth=(Range)obj;
if(lower<oth.lower) { return -1; }
if(lower>oth.lower) { return 1; }
if(upper<oth.upper) { return -1; }
if(upper>oth.upper) { return 1; }
return 0;
}
范围插入:
public Builder addRange(int fir, int las) {
if(fir!=-1) { fir&=0x001FFFFF; }
if(las!=-1) { las&=0x001FFFFF; }
if(codepoints==null || codepoints.length==0) {
codepoints=new Range[]{new Range(fir,las)};
}
else {
int idx=Range.findChar(codepoints,fir);
int ins=(idx<0 ? -(idx+1) : idx);
if(idx<0) {
if (ins>0 && fir==(codepoints[ins-1].upper+1)) { idx=(ins-1); }
else if(ins<codepoints.length && las>=(codepoints[ins ].lower-1)) { idx=ins; }
}
if(idx<0) {
codepoints=(Range[])Util.arrayInsert(codepoints,ins,new Range(fir,las));
}
else {
boolean rmv=false;
for(int xa=(idx+1); xa<codepoints.length && codepoints[xa].lower<=las; xa++) {
if(las<codepoints[xa].upper) { las=codepoints[xa].upper; }
codepoints[xa]=null;
rmv=true;
}
if(codepoints[idx].lower>fir || codepoints[idx].upper<las) {
codepoints[idx]=new Range((codepoints[idx].lower < fir ? codepoints[idx].lower : fir),(codepoints[idx].upper>las ? codepoints[idx].upper : las));
}
if(rmv) { codepoints=Range.removeNulls(codepoints); }
}
}
return this;
}
二分查找:
static int findChar(Range[] arr, int val) {
if(arr.length==1) {
if (val< arr[0].lower) { return -1; }
else if(val<=arr[0].upper) { return 0; }
else { return -2; }
}
else {
int lowidx=0;
int hghidx=(arr.length-1);
int mididx;
Range midval;
while(lowidx<=hghidx) {
mididx=((lowidx+hghidx)>>>1);
midval=arr[mididx];
if (val< midval.lower) { hghidx=(mididx-1); }
else if(val<=midval.upper) { return mididx; }
else { lowidx=(mididx+1); }
}
return -(lowidx+1);
}
}