给定任何一系列输入日期,其中单个状态为“打开”或“已关闭”,以便至少有一个输入日期(打开状态),这会导致单个日期(已关闭,最大日期)被添加到完成输出序列你会用什么算法来生成服从以下的输出?
1。没有连续的开放日期,也没有连续的关闭日期。
2。对于每个开放日期,只有一个截止日期。
3。第一个日期应为Open,最后一个日期应为Closed。
4。除了第一个开放日期和最后一个关闭日期之外,每个开放日期应该紧跟上一个关闭日期,或换句话说,每个关闭日期应该是下一个开放日期之前的一天。
5。最终日期为已结束日期和最长日期(在此示例中为9999-12-31)
这不是一个家庭作业,我在C#中实现了它,它的生产代码将执行数百万次。性能很重要,是的,但非常可读性。我使用的算法效果很好,但看起来很糟糕。任何语言欢迎。我会在必要时翻译。感谢。
示例1
input:
[2000-01-01,open]
output:
[2000-01-01,open]
[9999-12-31,closed]
示例2
input:
[2000-01-01,open]
[2001-01-01,open]
output:
[2000-01-01,open]
[2000-12-31,closed]
[2001-01-01,open]
[9999-12-31,closed]
示例3
input:
[2000-01-01,open]
[2004-04-30,closed]
output:
[2000-01-01,open]
[2004-04-30,closed]
[2004-05-01,open]
[9999-12-31,closed]
示例4
input:
[2000-01-01,open]
[2000-03-17,open]
[2002-09-11,closed]
[2003-04-07,closed]
output:
[2000-01-01,open]
[2000-03-16,closed]
[2000-03-17,open]
[2002-09-11,closed]
[2002-09-12,open]
[2003-04-07,closed]
[2003-04-08,open]
[9999-12-31,closed]
我敢问哪种语言最能解决这类问题?
答案 0 :(得分:5)
答案 1 :(得分:0)
您可以先生成所有开放日期的列表,然后通过从第一个开始日期减去一天来计算结束日期:
C#伪代码:
var opendates = input.Select ( date =>
date.Type == closing ? date.Date + 1day : date.Date
).Sort ();
closingdates = opendates.Skip (1).Select (date => date - 1).Append ( new Date [] { 9999-12-31 } );
答案 2 :(得分:0)
所以解决方案应该很快,因为性能在这里至关重要。此外,它应支持在线处理,因此当系统运行时,您可以随时添加新的开始/结束日期,并立即获得更新的计划。
由于此问题的主要操作是排序,我建议使用堆。堆中的每个节点都存储一个日期/状态对。该算法以空堆启动,并不断将其作为读取输入进行开发。当有新数据到来时,算法会将其插入到树中,该树需要O(lgN)。当有请求提取时间表时,算法执行有序遍历,其取O(N)。该算法还应该一次平衡自己以获得更好的性能。