我有一个BaseBallGame对象列表,包含开始和结束时间。我需要确保每个游戏都在一个单独的时间发生,以便用户可以观看所有游戏的直播。
我的算法为O(n^2)
。我需要至少让它成为nlog(n)
。
有人能指点我们如何改善我的实现性能吗?
public class GameTime {
public static Boolean canViewAll(Collection<BaseBallGame> baseBallGames) {
List<BaseBallGame> games_list = (List<BaseBallGame>) baseBallGames;
boolean isOverlap = false;
for (int i = 0; i < games_list(); i++) {
for (int j = i + 1; j < games_list(); j++) {
Date startA = games_list(i).getStart();
Date endA = games_list(i).getEnd();
Date startB = games_list(j).getStart();
Date endB = games_list(j).getEnd();
boolean isStartABeforeEndB = (startA.compareTo(endB)) < 0;
boolean isEndAAfterStartB = (endA.compareTo(startB)) > 0;
boolean isCurrentPairOverlap = false;
isCurrentPairOverlap = isStartABeforeEndB && isEndAAfterStartB;
if (isCurrentPairOverlap) {
isOverlap = true;
}
}
}
return !isOverlap;
}
boolean overlap(Date start1, Date end1, Date start2, Date end2){
return start1.getTime() <= end2.getTime() && start2.getTime() <= end1.getTime();
}
public static void main(String[] args) throws Exception {
SimpleDateFormat sdf = new SimpleDateFormat("y-M-d H:m");
ArrayList<BaseBallGame> baseBallGames = new ArrayList<BaseBallGame>();
baseBallGames.add(new BaseBallGame(sdf.parse("2015-01-01 20:00"), sdf.parse("2015-01-01 21:30")));
baseBallGames.add(new BaseBallGame(sdf.parse("2015-01-01 21:30"), sdf.parse("2015-01-01 23:00")));
baseBallGames.add(new BaseBallGame(sdf.parse("2015-01-01 23:10"), sdf.parse("2015-01-01 23:30")));
System.out.println(GameTime.canViewAll(baseBallGames));
}
}
class BaseBallGame {
private Date start, end;
public BaseBallGame(Date start, Date end) {
this.start = start;
this.end = end;
}
public Date getStart() {
return this.start;
}
public Date getEnd() {
return this.end;
}
}
答案 0 :(得分:5)
您正在描述Activity Selection Problem
A[i+1]
的开始时间是否大于A[i]
的结束时间。由于它涉及排序,因此它有一个O(n log n)
答案 1 :(得分:1)
如果您使用Comparator对列表进行排序,然后在列表中迭代一次并查看是否有任何重叠,该怎么办?
Java Array Sorting Algorithm:java.util.Arrays对实现Comparable或使用Comparator的对象使用mergesort。
Merge sort算法是平均/最佳/最差情况nlog(n)
。然后,一次迭代可以忽略不计。
答案 2 :(得分:0)
有许多排序算法,您可以在代码中实现它们。网站上的以下排序算法已经实施,并且还显示了时间复杂度。
https://www.toptal.com/developers/sorting-algorithms
Quicksort和Quicksort 3路分区是nlogn算法。
答案 3 :(得分:0)
如果您只是想检查是否存在冲突,那么您可以尝试
Set<BaseBallGame> baseBallGameSet = new HashSet<BaseBallGame>(games_list);
if(baseBallGameSet.size < games_list.size)
// Clash exists.
您可以在@thebenman建议之前将其视为优化。
答案 4 :(得分:0)
适应此问题的最有效算法是区间搜索树。你有开始时间和结束时间,意味着你有一个间隔。一旦你的游戏开始,如果它没有与其他游戏的时间重叠,那么把它放在树上。当你开始一个新游戏,然后把游戏时间放在一起,如果它与前一个游戏的时间重叠,那么树将报告,因为它有一个间隔。
不是每次都检查新游戏,而是将所有间隔放在树中,如果它与另一个间隔相交,那么树数据结构将自动检测并报告它。这种插入和删除算法的时间复杂度是~logN
,这是非常有效的。如果您有R个交叉点,那么复杂性将是~RlogN
,其中R
是交叉点的数量。
您还可以关注robert sedgewick here的视频。