C# Linq表达式速度慢-如果可能,需要进行优化

C# Linq表达式速度慢-如果可能,需要进行优化,c#,performance,linq,time-complexity,C#,Performance,Linq,Time Complexity,我有一个整数列表“NumberArrangeList”,按顺序包含62到92之间的31个整数,我正在提取第二个整数列表“extractedList”,其中将包含10个整数,其和等于“total”。问题是计算大约需要30秒,有没有办法加快速度 var numberRangeList = new List<int>() { 62, 63, ...92 }; var total = 772; var extractedList= (from

我有一个整数列表“NumberArrangeList”,按顺序包含62到92之间的31个整数,我正在提取第二个整数列表“extractedList”,其中将包含10个整数,其和等于“total”。问题是计算大约需要30秒,有没有办法加快速度

        var numberRangeList = new List<int>() { 62, 63, ...92 };
        var total = 772;
        var extractedList= (from n1 in numberRangeList
                      from n2 in numberRangeList
                      from n3 in numberRangeList
                      from n4 in numberRangeList
                      from n5 in numberRangeList
                      from n6 in numberRangeList
                      from n7 in numberRangeList
                      from n8 in numberRangeList
                      from n9 in numberRangeList
                      from n10 in numberRangeList
                      where n1 + n2 + n3 + n4 + n5 + n6 + n7 + n8 + n9 + n10 == total
                      select new List<int> { n1, n2, n3, n4, n5, n6, n7, n8, n9, n10 }).Take(1).First();
var numberRangeList=newlist(){62,63,…92};
var总计=772;
var extractedList=(来自NumberArrangeList中的n1
从NumberArrangeList中的n2开始
从编号列表中的n3开始
从编号列表中的n4开始
从编号列表中的n5开始
从编号列表中的n6开始
从NumberArrangeList中的n7开始
从NumberArrangeList中的n8开始
从NumberArrangeList中的n9开始
从NumberArrangeList中的n10开始
其中n1+n2+n3+n4+n5+n6+n7+n8+n9+n10==总计
选择新列表{n1,n2,n3,n4,n5,n6,n7,n8,n9,n10});

在我看来,您的查询会计算从公共号码池中提取的10个号码的所有可能组合。(或者,在数据库术语中,您正在计算一个非常大的叉积。)这可能需要处理很多组合。也许毫不奇怪,仅仅找到第一场比赛就需要30秒

如果我没有完全弄错的话,你的计算类似于所谓的。如果是这样的话,也许你可以通过研究这个众所周知的问题找到一个优化方案


更新:根据@Saverio Terracciano的评论,将您的问题视为背包问题的一个实例可能会带来比严格要求更复杂的问题。也许还可以看一下。

问题不在LINQ查询中-问题是您的算法复杂度为O(n^10)-大约完成了(92-62+1)^10个操作-即使对于现代cpu来说,这也是一个很大的工作。您可以使用背包动态规划算法解决问题,然后使用BFS(广度优先搜索)查找包含十个数字的结果。

性能问题不在LINQ中,而在问题本身。
这个问题在CS文献中是众所周知的,它被称为子集和。这是一个已知的问题,属于时间复杂性的NP完全类()。如果你不想探究(指数)问题的复杂性,你应该做一些次优解决方案的研究。

这需要永远的计算时间。令人惊讶的是,它甚至在太阳爆炸之前就回来了。这毕竟要进行大约2^50次运算。@usr:由于
。Take(1)
,当它找到第一个匹配项时,显示的计算将停止。这本身就需要OP的机器30秒。你的问题是背包问题的一个非常简单的特例,因为所有的数字都在连续的范围内[62,92]。你可以很容易地为[62*10,92*10]中的所有数字构造一个匹配项。就个人而言,这不仅仅是一个权重为1的背包问题,而是一个子集和问题实例。离题:你可以像这样构建
numberRangeList
:Enumerable.Range(62,93).ToList()。实际上,没有必要用手把它全部写下来。谢谢,我是linq的新手,所以假设如果我添加“.take(1)”,这会加快事情的发展,确实如此。但这一切都取决于你感兴趣的结果<代码>.Take(1)意味着您只能从几个可能的数字组合中得到一个结果,加起来等于772。Take不是必需的,因为您首先可以将子集和问题视为背包的一个特例,因为您拥有权重为1的所有元素,而不关心可用的总重量。虽然这两个问题在渐近上具有可比的复杂性,但以一种更容易理解的方式处理这样的问题更容易(不必处理额外的维度)。@saverioterraciano:好的,这是有道理的。但是,说我们不是在处理背包是错误的;不必把它当作一个,因为它在子集和上引入了不必要的复杂性。子集和是背包的特例。只是项目值和权重等于数字。在他的情况下,他不需要寻找次优解-他的NumberArrangeList获得的最大和值为92*10,动态规划数组大小为9200*32-这对pc来说不是很多工作。也就是说,如果他的场景保持不变,如果边界发生变化,会发生什么?那么除了启发式(至少如果P!=NP)之外,就没有其他方法了,要么是启发式算法,要么是近似算法,这就是为什么我在最后一句中说,如果他不想探索指数问题的复杂性,他应该研究次优解(近似或启发)。