C# 计算打开事件的最大数量

C# 计算打开事件的最大数量,c#,linq,datetime,C#,Linq,Datetime,我有一个活动列表,有开始日期和结束日期,如下所示: DateOpen | DateClose -----------|----------- 01.01.2000 | 05.01.2000 02.01.2000 | 02.01.2000 所以在01.01。我们有一个公开活动,在02.01。我们有两个公开赛,从那时起到05.01我们只有一个公开赛 现在的任务是计算打开事件的最大数量,在本例中为2 我就是找不到解决这个问题的好办法,也许其他人有个好主意。我在linq to对象列表中有所有事件,

我有一个活动列表,有开始日期和结束日期,如下所示:

DateOpen   | DateClose
-----------|-----------
01.01.2000 | 05.01.2000
02.01.2000 | 02.01.2000
所以在01.01。我们有一个公开活动,在02.01。我们有两个公开赛,从那时起到05.01我们只有一个公开赛

现在的任务是计算打开事件的最大数量,在本例中为2

我就是找不到解决这个问题的好办法,也许其他人有个好主意。我在linq to对象列表中有所有事件,因此排序、筛选等都很容易


我试过什么?没什么,因为我不知道从哪里开始:)

因为实际答案只在注释中:

events.Select(i => events.Where(j => i.DateOpen <= j.DateClose && i.DateClose >= j.DateOpen).Count()).Max()
events.Select(i=>events.Where(j=>i.DateOpen=j.DateOpen.Count()).Max()
var max=events.Select(i=>events.Where(j=>i.DateOpen=j.DateOpen.Count())
.Max();
但是它的复杂性是O(n^2),这可能并不适用于所有情况


目前还想不出更快的解决方案。

下面是一个列表解决方案。我还包括了一个分割的开放和关闭太对。(因为我希望这就是存储数据的方式。)由于walk需要先打开后关闭,我在s中添加了,而不仅仅是按日期排序,并且需要创建事件对象的顺序。如果先关闭后打开,则此操作将失败

这是用linqpad编写和测试的。复制并粘贴它,它将运行。在LinqPad.com上获取(然后爱上它)

我希望这是O(logn),因为
OrderBy
应该是O(logn)

void Main()
{
列表列表=新列表();
添加(新事件(新日期时间(2000,1,1),新日期时间(2000,5,1));
添加(新事件(新日期时间(2000,2,1),新日期时间(2000,2,1));
var datelist=eList.Select(item=>new{t=“open”,d=item.open,s=item.open.Ticks*10})
.Concat(eList.Select(item=>new{t=“close”,d=item.close,s=(item.close.Ticks*10)+1}))
.OrderBy(item=>item.s);
var max=datelist.Aggregate(
新的{curCount=0,max=0},
(结果,项目)=>{
如果(项目t==“打开”)
{
如果(result.max<(result.curCount+1))
返回(新的{curCount=result.curCount+1,max=result.curCount+1});
其他的
返回(新的{curCount=result.curCount+1,max=result.max});
}
其他的
返回(新的{curCount=result.curCount-1,max=result.max});
},
结果=>result.max);
最大转储();
}
//在此处定义其他方法和类
公开课活动
{
公共日期时间打开{get;set;}
公共日期时间关闭{get;set;}
公共事件(日期时间不打开,日期时间包含)
{

if(inOpen
events.Select(i=>events.Where(j=>i.DateOpen=j.DateOpen.Count()).Max()
(我现在不编程C#所以可能会错过一些东西)@zerkms:这可能会起作用。它是O(n^2),但这对这个应用程序来说可能没问题。@Gabe:我在考虑一些树结构,但从来没有将它们应用于间隔。
DateClose
是包含的还是独占的?我有包含时间的日期,所以它会降到第二个。所以我认为它是独占的,即使我真的不理解这个问题。你可以用O(N lg(N))来做它通过对开放时间和关闭时间进行排序,然后按顺序记录开放事件的当前数量(以及开放事件的最大数量)。@Gabe:“按顺序记录开放事件的当前数量”---这就是问题所在,不是吗?非常感谢!我刚刚尝试过,但它给我的开放事件比现在更多(但我必须再次检查,以确保这不是我在数据中的错误)。@zerkms-聚合没那么难,请看我的回答是的,我现在明白了。我假设它是
O(n logn)
但是,由于它是作为一种稳定的QuickSort实现的,作为一种替代方案,您还可以将其转换为
打开
关闭
字符串(或布尔值,或其他任何内容)列表在每个打开的
++
计数器上,以及在每个关闭的
-
上。记住最大到达值哇,感谢大家的回答,这一个很好!+1,如果可以的话接受更多:)非常感谢!@zerkms:很抱歉,这一个给了我正确的打开事件数,你的返回数也多了一些(即使我不知道为什么)。但是你的+1也是:)@Marc:我的作品包括,这一个-独家。所以对于间隔
1-2;2-3
my将返回2,这-1。所以显而易见的解决方案是使用

var max = events.Select(i => events.Where(j => i.DateOpen <= j.DateClose
                                            && i.DateClose >= j.DateOpen).Count())
                .Max();
void Main()
{
  List<Event> eList = new List<Event>();
  eList.Add(new Event(new DateTime(2000,1,1),new DateTime(2000,5,1)));
  eList.Add(new Event(new DateTime(2000,2,1),new DateTime(2000,2,1)));

  var datelist = eList.Select(item => new { t = "open", d = item.open, s = item.open.Ticks*10 })
        .Concat(eList.Select(item => new { t = "close", d = item.close, s = (item.close.Ticks*10)+1 }))
        .OrderBy(item => item.s);

  var max = datelist.Aggregate(
            new { curCount = 0, max = 0 },
            (result,item) => {
               if (item.t == "open")
               {
                  if (result.max < (result.curCount+1))
                    return(new { curCount = result.curCount+1, max = result.curCount+1 });
                  else
                    return(new { curCount = result.curCount+1, max = result.max });
               }
               else
                 return(new { curCount = result.curCount-1, max = result.max });
            },
            result => result.max);

   max.Dump();
}

// Define other methods and classes here

public class Event
{
    public DateTime open { get; set; }
    public DateTime close { get; set; }

    public Event(DateTime inOpen, DateTime inClose)
    {
      if (inOpen <= inClose)
      {
        open = inOpen;
        close = inClose;
      }
      else throw(new Exception("Can't close at "+inClose.ToShortDateString()+" before you open at "+inOpen.ToShortDateString()));
    }
}