我有一个所有行的文本文件:
8:30 8:50 1
..........
20:30 20:35 151
每一行都是In-net中与其相关的新用户连接。
目标是找到数量达到最大值的时间段。 那么,也许有人知道可以帮助我完成这项任务的算法(多个交叉点)?找到这个任务对我来说非常重要(因为我是编程新手),我有一些想法,但我发现它们很糟糕,这就是为什么我应该从数学算法开始,以达到实现目标的最佳方式。
答案 0 :(得分:0)
你可以这样做:
string[] lines=System.IO.File.ReadAllLines(filePath)
var connections = lines
.Select(d => d.Split(' '))
.Select(d => new
{
From = DateTime.Parse(d[0]),
To = DateTime.Parse(d[1]),
Connections = int.Parse(d[2])
})
.OrderByDescending(d=>d.Connections).ToList();
连接将包含排序列表,其中前面的结果是
答案 1 :(得分:0)
首先,我们必须做出一些假设。
解决方案的第一阶段是解析。给定一系列行,我们得到System.DateTime对的序列 - 按顺序为每个句点添加一对。
static Tuple<DateTime, DateTime> Parse(string line)
{
var a = line.Split()
.Take(2) // take the start and end times only
.Select(p =>
DateTime.ParseExact(p, "H:m",
CultureInfo.InvariantCulture))
.ToArray();
return Tuple.Create(a[0], a[1]);
}
下一阶段是算法本身。它有两个部分。首先,我们发现局部最大值为开始时间,结束时间和连接数的三元组。其次,我们从第一部分产生的集合中选择绝对最大值:
File.ReadLines(FILE_PATH).Select(Parse).GetLocalMaximums().Max(x=>x.Item3)
File.ReadLines(FILE_PATH).Select(Parse).GetLocalMaximums()
.Aggregate((x, y) => x.Item3 > y.Item3 ? x : y))
File.ReadLines(FILE_PATH).Select(Parse).GetLocalMaximums()
.Aggregate((x, y) => x.Item3 >= y.Item3 ? x : y))
最复杂的部分是检测局部最大值。
本地最大检测的源代码
static IEnumerable<Tuple<DateTime, DateTime, int>>
GetLocalMaximums(this IEnumerable<Tuple<DateTime, DateTime>> ranges)
{
DateTime lastStart = DateTime.MinValue;
var queue = new List<DateTime>();
foreach (var r in ranges)
{
queue.Add(r.Item2);
var t = queue.Min();
if (t < r.Item1)
{
yield return Tuple.Create(lastStart, t, queue.Count-1);
do
{
queue.Remove(t);
t = queue.Min();
} while (t < r.Item1);
}
if (t == r.Item1) queue.Remove(t);
else lastStart = r.Item1;
}
// yield the last local maximum
if (queue.Count > 0)
yield return Tuple.Create(lastStart, queue.Min(), queue.Count);
}
虽然使用List(T)不是最好的决定,但它很容易理解。使用排序版本的列表可以获得更好的性能。用结构替换元组将消除大量的内存分配操作。