Java 从给定的日期范围列表中查找所有重叠的日期范围
我有一个BookingDateRange列表,其中BookingDateRange是:Java 从给定的日期范围列表中查找所有重叠的日期范围,java,date,Java,Date,我有一个BookingDateRange列表,其中BookingDateRange是: public class BookingDateRange { private Date fromDate; private Date toDate; //getters & setters of properties } 要求: /** * Checks if any of the dates overlap. * * @par
public class BookingDateRange {
private Date fromDate;
private Date toDate;
//getters & setters of properties
}
要求:
/**
* Checks if any of the dates overlap.
*
* @param dateRangeList the date range list
* @param overlappingDatePairs the overlapping date pairs where overlappingDatePair is stored in the format dateRange1_dateRange2
* @return true, if any of the dates overlap.
*/
public static boolean isOverlappingDates(
List<BookingDateRange> dateRangeList,
List<String> overlappingDatePairs) {
boolean isOverlap = false;
for (int index1 = 0; index1 < dateRangeList.size(); index1++) {
for (int index2 = index1 + 1; index2 < dateRangeList.size(); index2++) {
// Overlap exists if (StartA <= EndB) and (EndA >= StartB)
Date startA = dateRangeList.get(index1).getFromDate();
Date endA = dateRangeList.get(index1).getToDate();
Date startB = dateRangeList.get(index2).getFromDate();
Date endB = dateRangeList.get(index2).getToDate();
boolean isStartABeforeEndB = (startA.compareTo(endB)) < 0;
boolean isEndAAfterStartB = (endA.compareTo(startB)) > 0;
boolean isCurrentPairOverlap = false;
isCurrentPairOverlap = isStartABeforeEndB && isEndAAfterStartB;
if (isCurrentPairOverlap) {
overlappingDatePairs.add(index1 + "_" + index2);
isOverlap = true;
}
}
}
return isOverlap;
}
/**
* Checks if any of the dates overlap.
*
* @param dateRangeList the date range list
* @param overlappingDatePairs the overlapping date pairs where overlappingDatePair is stored in the format dateRange1_dateRange2
* @return true, if any of the dates overlap.
*/
public static boolean isOverlappingDates(
List<BookingDateRange> dateRangeList,
List<String> overlappingDatePairs) {
boolean isOverlap = false;
for (int index1 = 0; index1 < dateRangeList.size(); index1++) {
for (int index2 = index1 + 1; index2 < dateRangeList.size(); index2++) {
// Overlap exists if (StartA <= EndB) and (EndA >= StartB)
Date startA = dateRangeList.get(index1).getFromDate();
Date endA = dateRangeList.get(index1).getToDate();
Date startB = dateRangeList.get(index2).getFromDate();
Date endB = dateRangeList.get(index2).getToDate();
boolean isStartABeforeEndB = (startA.compareTo(endB)) < 0;
boolean isEndAAfterStartB = (endA.compareTo(startB)) > 0;
boolean isCurrentPairOverlap = false;
isCurrentPairOverlap = isStartABeforeEndB && isEndAAfterStartB;
if (isCurrentPairOverlap) {
overlappingDatePairs.add(index1 + "_" + index2);
isOverlap = true;
}
}
}
return isOverlap;
}
输入2:
日期范围列表[0]=2012年12月23日至2012年12月27日
日期范围列表[1]=2012年1月1日至2012年1月23日
输出2:
isOverlappingDates=false
重叠日期对=[]
我的解决方案:
/**
* Checks if any of the dates overlap.
*
* @param dateRangeList the date range list
* @param overlappingDatePairs the overlapping date pairs where overlappingDatePair is stored in the format dateRange1_dateRange2
* @return true, if any of the dates overlap.
*/
public static boolean isOverlappingDates(
List<BookingDateRange> dateRangeList,
List<String> overlappingDatePairs) {
boolean isOverlap = false;
for (int index1 = 0; index1 < dateRangeList.size(); index1++) {
for (int index2 = index1 + 1; index2 < dateRangeList.size(); index2++) {
// Overlap exists if (StartA <= EndB) and (EndA >= StartB)
Date startA = dateRangeList.get(index1).getFromDate();
Date endA = dateRangeList.get(index1).getToDate();
Date startB = dateRangeList.get(index2).getFromDate();
Date endB = dateRangeList.get(index2).getToDate();
boolean isStartABeforeEndB = (startA.compareTo(endB)) < 0;
boolean isEndAAfterStartB = (endA.compareTo(startB)) > 0;
boolean isCurrentPairOverlap = false;
isCurrentPairOverlap = isStartABeforeEndB && isEndAAfterStartB;
if (isCurrentPairOverlap) {
overlappingDatePairs.add(index1 + "_" + index2);
isOverlap = true;
}
}
}
return isOverlap;
}
/**
*检查是否有任何日期重叠。
*
*@param dateRangeList日期范围列表
*@param overlappingDatePairs重叠的日期对,其中overlappingDatePairs以dateRange1\u dateRange2格式存储
*@return true,如果任何日期重叠。
*/
公共静态布尔isOverlappingDates(
列表日期范围列表,
列表重叠(日期对){
布尔值isOverlap=false;
对于(int index1=0;index10;
布尔值isCurrentPairOverlap=false;
isCurrentPairOverlap=isstartabeforendb&isendaafterstart;
如果(isCurrentPairOverlap){
重叠日期对。添加(index1+“”+index2);
isOverlap=真;
}
}
}
返回等重叠;
}
这种方法的复杂性是O(n^2)。是否可能有更好的复杂性?无法得到更复杂的算法
当时确实遇到了一些解决方案。但没有一个能完全满足要求
谢谢,
Shikha我认为你不能做得更好,因为你必须将每个预订日期范围与其他日期范围进行比较 因此,每个元素需要
O(n)个比较
,而您有n个元素
因此,我的解决方案将以复杂性换取内存。它假设日期的范围相对有限(不能将公元前5000年和公元6000年的日期混用) 1创建
地图
2对于每个范围,选择第一个日期并将其转换为GregoriaCalendar
。以“yyyy/MM/dd”(或类似格式)获取日期
2a如果“yyyy/MM/dd”字符串已在映射中,请将新范围添加到列表中
2b如果不是,则使用包含范围的新列表添加条目
2c每天增加格里高利安达令。重复此操作,直到达到范围内的最后一个日期
3对所有范围重复上述步骤
4列出映射的键(如果使用“yyyy/MM/dd”格式,则排序很简单)。检查关联列表的大小。这里是O(nlog(n)),或者很明显,如果存在大量碰撞,则是O(碰撞数)。我曾经工作过的一家公司在面试中也提出了类似的问题
private static class BookingTuple implements Comparable<BookingTuple> {
public final Date date;
public final boolean isStart;
public final int id;
public BookingTuple(Date date, boolean isStart, int id) {
this.date = date;
this.isStart = isStart;
this.id = id;
}
@Override
public int compareTo(BookingTuple other) {
int dateCompare = date.compareTo(other.date);
if (dateCompare != 0) {
return dateCompare;
} else {
if (!isStart && other.isStart) {
return -1;
} else if (isStart && !other.isStart) {
return 1;
} else {
return 0;
}
}
}
}
public static boolean isOverlappingDates(List<BookingDateRange> dateRangeList, List<String> overlappingDatePairs) {
List<BookingTuple> list = new ArrayList<BookingTuple>();
for (int i = 0; i < dateRangeList.size(); i++) {
Date from = dateRangeList.get(i).getFromDate();
Date to = dateRangeList.get(i).getToDate();
list.add(new BookingTuple(from, true, i));
list.add(new BookingTuple(to, false, i));
}
Collections.sort(list);
boolean overlap = false;
HashSet<Integer> active = new HashSet<Integer>();
for (BookingTuple tuple : list) {
if (!tuple.isStart) {
active.remove(tuple.id);
} else {
for (Integer n : active) {
overlappingDatePairs.add(n + "_" + tuple.id);
overlap = true;
}
active.add(tuple.id);
}
}
return overlap;
}
private静态类BookingTuple实现了可比较的{
公开最终日期;
公共服务启动;
公共最终int id;
public BookingTuple(日期、布尔值isStart、整数id){
this.date=日期;
this.isStart=isStart;
this.id=id;
}
@凌驾
公共整数比较(预订其他整数){
int dateCompare=date.compareTo(其他.date);
如果(日期比较!=0){
返回日期比较;
}否则{
如果(!isStart&&other.isStart){
返回-1;
}else if(isStart&!other.isStart){
返回1;
}否则{
返回0;
}
}
}
}
公共静态布尔isOverlappingDates(列表日期范围列表、列表重叠日期对){
列表=新的ArrayList();
对于(int i=0;i
看起来复杂性是O(n^2)而不是O(2^n)编辑的:D@gtgaxiola哎呀。。打字错误对O(n^2)。在问题中编辑。我没有检查O(n)
声明,因此我正在考虑改进2^n
复杂性(这意味着额外的开销通常没有意义)。看到gtgaxiola的修正,我的方法改进较少,但如果范围数较多且覆盖的日期较小,则仍然有用。按照您的逻辑,排序也有n^2的下限,这显然是不正确的。见公认的答案。