我试图找出如何以干净的方式编码二进制搜索返回缺少元素的插入点的事实。
我将此用于查找非重叠区间的最大子集的算法问题。
我所做的是在对间隔进行排序后,保持每个间隔的开始时间与已选择的间隔结束时间不重叠。
虽然我可以进行线性搜索,但我认为使用二进制搜索会更好。我对吗?
所以我做了以下操作,虽然它看起来是正确的,但它容易出错,我认为可以更好地使用API。
我正在做的是在结束间隔上进行二进制搜索,然后查看它是否与前一个或下一个重叠(使用二进制搜索返回的插入点)。
我的逻辑是否正确?另外我相信这个算法可以是一个很好的练习,所以我看起来是一个干净的Java版本。
private boolean nonOverlapping(Pair interval, SortedSet<Pair> selectedIntervals) {
if(selectedIntervals.isEmpty())
return true;
if(selectedIntervals.contains(interval)){
return true;
}
Pair[] sortedSelections = selectedIntervals.toArray(new Pair[0]);
int pos = Arrays.binarySearch(sortedSelections, interval, new Comparator<Pair>() {
@Override
public int compare(Pair o1, Pair o2) {
return o1.getStart() - o2.getEnd();
}
});
pos = (-pos) -1;
if(pos == sortedSelections.length){
if(sortedSelections[pos - 1].getEnd() < interval.getStart()){
return true;
}
}
else if(sortedSelections[pos].getEnd() > interval.getStart()){
if(pos + 1 < sortedSelections.length){
if(sortedSelections[pos + 1].getEnd() < interval.getStart()){
return false;
}
}
if(pos - 1 >= 0){
if(sortedSelections[pos - 1].getEnd() < interval.getStart()){
return false;
}
}
return true;
}
return false;
}
答案 0 :(得分:3)
找到一系列间隔中最大的非重叠子集的问题是greedy algorithm的经典应用。标准的贪婪算法如下:
从该算法可以清楚地看出,结果集不包含任何重叠间隔,因为算法的每个步骤都会从未来的考虑中删除所有冲突的间隔。
要确保这是最佳的,您可以使用交换参数来表明无法找到更好的解决方案。您可以在线查找详细信息,例如in this set of lecture slides。
希望这有帮助!
答案 1 :(得分:0)
重叠的“正常”比较无法使用?
@Override
public int compare(Pair o1, Pair o2) {
return o1.getStart() > o2.getEnd() ? 1
: o1.getEnd() < o2.getStart() ? -1
: 0;
}
的说明强> 的
这包括
[o2s .. o2e] [o1s .. o1e] o1s > o2e when after -> +1
[o1s .. o1e] [o2s .. o2e] o1e < o2s when before -> -1
otherwise overlap -> 0
需要所有4个变量:o1s,o1e,o2s,o2e。