我将在底部解释问题的来源,但这里是陈述。假设我有两个非负整数列表,它们分别是 (A[0] ... A[n])
和 (B[0] ... B[m])
。它们严格递增,因此对于所有的 i
,A[i+1] > A[i]
,并且对于 B
也是如此。我想收集所有 n * m
个元素对,并按它们的和的大小进行排序。
例如,如果 A = (0 1 2)
并且 B = (1 4)
,那么我希望最终收集以下内容 ((0 1) (1 1) (2 1) (0 4) (1 4) (2 4))
。如果存在平局,则我不关心我以什么顺序收集这两个元素。例如,如果 A = (0 1)
并且 B = (0 1)
,那么我不介意先拿到混合项中的哪一个,(0 1)
或者 (1 0)
。
显然,我希望这个算法相对高效。我希望它的时间复杂度为 m * n
。具体来说,我希望有序的输入使这个问题比我不知道输入时的等价问题更容易解决。当我第一次提出问题时,在我脑海里想到的是我们需要存储的状态量。我希望它只需要固定数量的状态量,但或许这是不切实际的。(自从那以后,我尝试了很多方法都失败了!)
这段代码实际上是用Lisp编写的,但我认为问题陈述与此无关。输入最自然的方式可能是单向链表,但我不管怎样都需要提前翻转它们,因此如果随机访问很重要,我可以将它们变成数组。如果相关的话,我预计这将主要用于相当小的列表,因此在运行时间中有一个巨大的常数项/常数因子可能排除了一种解决方案。(虽然我对算法想法很感兴趣!)
背景:我一直在研究Maxima的源代码,它是一个计算机代数系统,特别是它的两个多项式相乘的代码。多项式以“稀疏格式”表示,因此x^5 + x^2 + 2
可能显示为(5 1 2 1 0 2)
,先是降序指数,后跟它们各自的系数。为了有效地计算乘积,我真正想做的是将零次项收集在一起,然后是一次项等。当前的代码通过进行半心半意的尝试以获得效率,然后执行一种通用的多项式加法来处理不期望的系数顺序。我觉得我们应该能做得更好!
sorted([(a,b) for a in A for b in B], key=sum)
- Robᵩ