【发布时间】:2016-08-10 03:53:59
【问题描述】:
所以我得到了一大堆列表(大约 200k)。每个都包含数字 0 到 27 的子集。我想返回两个列表,其中它们的长度的乘积大于任何其他列表对的长度的乘积。还有另一个条件,即这些列表没有共同的数字。
我为此找到了一个算法(不记得来源,为道具的非特异性道歉),它利用了数字 0 到 27 的总子集比字典中的单词少的事实。
我做的第一件事是遍历所有列表,找到组成它的唯一整数子集,并将其索引为 0 到 1
def index_lists(lists):
index_hash = {}
for raw_list in lists:
length = len(raw_list)
if length > index_hash.get(index,{}).get("length"):
index = find_index(raw_list)
index_hash[index] = {"list": raw_list, "length": length}
return index_hash
这给了我最长的列表和列表的长度,每个子集实际上包含在给定列表的集合中。当然,并非必须包含从 0 到 (1
然后我想要的是,对于每个子集 0 到 1
def at_most_hash(index_hash):
most_hash = {}
for i in xrange(1<<28): # pretty sure this is a bad idea
max_entry = index_hash.get(i)
if max_entry:
max_length = max_entry["length"]
max_word = max_entry["list"]
else:
max_length = 0
max_word = []
for j in xrange(28): # again, probably not great
subset_index = i & ~(1<<j) # gets us a pre-computed subset
at_most_entry = most_hash.get(subset_index, {})
at_most_length = at_most_entry.get("length",0)
if at_most_length > max_length:
max_length = at_most_length
max_list = at_most_entry["list"]
most_hash[i] = {"length": max_length, "list": max_list}
return most_hash
这个循环显然需要好几次才能完成。我觉得我对 python 足够陌生,以至于我选择如何迭代和使用什么数据结构可能完全是灾难性的。更不用说试图填满字典的预期记忆问题了。是否有更好的结构或包用作数据结构?还是设置迭代的更好方法?或者也许我可以更稀疏地做到这一点?
算法的下一部分只是循环遍历我们给出的所有列表,并通过在 at_most_hash 中查找子集的 max_length 和互补子集的最大长度的乘积,取其中的最大值。
这里有什么建议吗?感谢您耐心地解决我冗长的问题,以及编写代码时不太体面的尝试。
理论上,这仍然是比单独使用列表集合更好的方法,因为这种方法大约是 o(200k^2) 而这个大约是 o(28*2^28 + 200k),但我的实现阻碍了我。
【问题讨论】:
-
我认为这篇文章更适合 [code-review]。
-
你的第二句话让我很困惑:“每个都包含数字 0 到 27。”你真的是说它们包含这些数字的一个子集吗?否则问题的其余部分毫无意义,因为每个列表都有相同的数字和相同的长度。
-
@JulienBernu:啊,那是一个单独的堆栈
站点吗?道歉。 -
@Blckknght:是的,我的意思是子集。我会编辑。
-
@AsinglePANCAKE 不用担心。是的:codereview.stackexchange.com
标签: python algorithm performance optimization data-structures