从总和最大的列表中产生元素

问题描述

我有几个排序的整数列表,长度可能不同,元素可能重复。我想编写一个生成组合的生成器,每个列表中的一个元素,按组合总和的降序排列。所以,如果我的列表是:

l_1 = [10,9,8,5,2]
l_2 = [15,7]
l_3 = [8,4,2,2]

我想回来:

(10,15,8),# sum=33
(9,# sum=32
(8,# sum=31
(10,4),# sum=29
(9,# sum=28
(5,# sum=28

等等。当多个组合产生相同的总和时,我不关心组合返回的顺序(例如,上面的最后两行可以颠倒而不会产生任何后果)。

我知道我可以使用 itertools.product 然后对结果进行排序,但我的列表可能很长,而且我可能有很多,并且在迭代总和时,我最终会达到停止点,因此无需将所有内容都存储在内存中。速度很重要,但我不确定像这样的事情的最佳时间复杂度(我不是很精通那种东西)。

编辑:到目前为止,我最好的解决方案是结合我见过的其他一些 SO 帖子。这个想法是最大的总和是每个列表中的第 0 个元素。所以指针在第一次迭代时是 (0,0)。然后,下一个最高的总和必须是 (1,0) 或 (0,1,1),因此将它们添加到优先级等于对应于以下元素的总和的 heapq那些指针。跟踪“可见”指针以避免重复。

import heapq

def best_search(*sequences):
    # Assumes sequences are passed pre-sorted from high to low (reverse order).
    # If not,sort them here.
    num_seqs = len(sequences)
    start = (0,) * num_seqs
    queue = [(0,start)]
    seen = set(start)
    while queue:
        priority,pointers = heapq.heappop(queue)
        yield pointers
        for i in range(num_seqs):
            if pointers[i] + 1 < len(sequences[i]):
                new_pointers = list(pointers)
                new_pointers[i] += 1
                new_pointers_t = tuple(new_pointers)
                if new_pointers_t not in seen:
                    seen.add(new_pointers_t)
                    priority = sum(seq[pointer] for seq,pointer in zip(sequences,new_pointers_t))
                    heapq.heappush(queue,(-priority,new_pointers_t))

它对前几百万个组合效果很好,但最终运行得很慢;我怀疑这是因为 seen 集变得非常大,并且针对该集检查新的可能的指针元组非常耗时。任何改进表示赞赏!

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)