我有一个会话到期时间和会话超时值列表。 所以我可以让会话开始时间从到期时间减去超时。
我知道如何检查两个日期是否重叠:
public boolean isOverlapped(LocalDateTime start1, LocalDateTime end1,
LocalDateTime start2, LocalDateTime end2) {
return (start1.isBefore(end2) || start1.equals(end2))
&& (start2.isBefore(end1) || start2.equals(end2));
}
但不知道如何使用日期列表。
结果我希望列表中包含最长的重叠(并发)会话链。 感谢任何帮助!
答案 0 :(得分:0)
首先,创建一个代表这些会话的新课程(如果你还没有):
class Session {
private LocalDateTime start;
private LocalDateTime end;
public boolean isOverlapped(Session other) {
return (start.isBefore(other.end) || start.equals(other.end))
&& (end.isAfter(other.start) || end.equals(other.start));
}
...
}
您的输入列表必须是Session
s。
接下来,这是一个执行您要求的算法;它接受一个列表并检查每个元素是否与列表中的任何其他元素重叠(除了它自身)。如果是这种情况,则将其放在结果列表中:
public static List<Session> filter(List<Session> in) {
List<Session> result = new ArrayList<>();
for(Session current : in) {
for(Session other : in) {
if(current != other && current.isOverlapped(other)) {
result.add(current);
break;
}
}
}
return result;
}
以下是一个示例程序:Ideone
结果将是一个包含与任何其他会话同时发生的会话的列表。
答案 1 :(得分:0)
这是一个相当经典的问题。您没有在时间或间隔数方面指定是否需要最长的会话,但它们的工作方式相同。
首先按开始时间对所有会话进行排序。然后逻辑如下:
current_chain = []
best_chain = []
for session in sessions_sorted_by_start:
if session doesn't overlap with any session in curent_chain: [1]
update best_chain if current_chain is better [2]
current_chain = []
current_chain.insert(session) [3]
update best_chain if current_chain is better [2]
这里的想法如下:我们维持当前的链条。如果新会话与链中的任何其他会话重叠,我们只需将其添加到链中。如果它不与当前链中的任何会话重叠,那么它的开始是从当前链中最远会话结束的右侧开始,因此没有其他剩余会话将与当前链中的任何内容重叠(因为它们是按开始日期排序)。这意味着当前的链条只要它能够获得,所以我们可以根据目前的最佳链条([2])检查它是否优于基于任何标准(时间或会话数),并重置它。
现在,为了使其在时间上呈线性,在常数时间内对[1]的会话和链进行重叠检查会很酷。如果对于链条始终保持最远的会话,这很容易完成。要做到这一点,当您在[3]处插入新会话时,如果其结束超出当前最远会话的结束,则更新最远的会话,否则不要。这种方式在[1]你只需要检查最远会话的重叠,而不是检查所有这些,这使得特定的检查恒定时间,整个算法线性(如果你不考虑初始排序,这是当然O(n log n)
)。