我有以下问题,最好在图中描述: 考虑以下序列(可以是任何类型的序列:数字,日期(在我的情况下是其日期)等。)
我想找到最长连续序列的所有组,如后一个例子中的输出,即包含最长序列的最小组数。
我想过进行某种排序/排序(min / max似乎没有太大的帮助,因为我可能有空隙),首先是左点然后是右边,但我不是确定无论如何。
答案 0 :(得分:4)
我会将起点和终点组合成一个排序顺序,然后按顺序处理它们,保持所见起点数的运行计数减去看到的终点数。当此计数器降至零时,您将获得完整间隙的开始。根据邻接线是否计算为零长度间隙,您可以在结束情况下对结束点之前或之后的起点进行排序。
答案 1 :(得分:3)
上次编写类似这样的内容时,只是吐出了一些伪代码:
var outputRanges = new List<Range>();
foreach (var range in inputRanges)
{
// Let Range.Touches(Range) define a function that returns true
// iff the two ranges overlap at all (that is, A.Start and/or A.End
// is between B.Start and B.End)
var overlaps = outputRanges.Where(range.Touches).ToList();
// If there are no overlaps, then simply add it to the output
if (!overlaps.Any())
{
outputRanges.Add(range);
}
// If there are overlaps, merge them
else
{
outputRanges.RemoveAll(overlaps);
overlaps.Add(range);
outputRange.Add(new Range() {
Start = overlaps.Min(_=>_.Start),
End = overlaps.Max(_=>_.End)
});
}
}
答案 2 :(得分:0)
我没有在C#中使用它,但确实必须在sql中解决这个确切的问题,也许这会给你一个关于如何将其转换为C#的提示
select Resource_ID, Appointment_date, Min(NewStartTime) Start_Time, MAX(End_Time) End_Time
into #CleanedBlockTimes
from
(
select *,
NewStartTime = Dateadd(mi, v.number, t.Start_Time),
NewStartTimeGroup =
dateadd(mi,
1- DENSE_RANK() over (partition by Resource_ID, Appointment_date order by Dateadd(mi, v.number, t.Start_Time)),
Dateadd(mi, v.number, t.Start_Time))
from #BlockTimes t
inner join master..spt_values v
on v.type='P' and v.number <= DATEDIFF(mi, Start_Time, End_Time)
) X
group by Resource_ID, Appointment_date, NewStartTimeGroup
order by Resource_ID, Appointment_date, Start_Time
答案 3 :(得分:0)
在范围的开头排序。
从列表的开头开始,将结束时间与列表中下一个项目的开头进行比较。如果它们重叠,则将结束时间替换为当前记录的结束时间的最大值和下一记录的结束时间。删除下一条记录。重复。
如果没有重叠前进到下一条记录并重复。
O(n log n)用于排序,O(n)用于编译。总的来说,o(n log n)。