这是我的问题:
我有一个大整数(0到2 ^ 32-1之间的任何地方)。我们把这个号码称为X. 我还有一个整数列表,目前未分类。它们都是唯一的数字,大于0且小于X.假设此列表中有大量项目,假设超过100,000个项目。
我需要在此列表中找到最多3个数字(我们称之为A,B和C),它们加起来为X. A,B和C都需要在列表中,并且它们可以重复(例如,如果X是4,我可以有A = 1,B = 1和C = 2,即使1只出现一次清单)。
A,B和C可以有多种解决方案,但我只需要尽可能以最快的方式找到一种可能的解决方案。
我尝试过这样创建一个for循环结构:
For A in itemlist:
For B in itemlist:
For C in itemlist:
if A + B + C == X:
exit("Done")
但由于我的整数列表包含超过100,000个项目,因此使用的内存太多而且耗时太长。
有没有办法找到A,B和C的解决方案而不使用疯狂的内存或花费大量的时间?提前谢谢。
答案 0 :(得分:3)
您可以使用类似
的设置将运行时间从n ^ 3减少到n ^ 2s = set(itemlist)
for A in itemlist:
for B in itemlist:
if X-(A+B) in s:
print A,B,X-(A+B)
break
如果要保存内存,也可以对列表进行排序并使用二进制搜索
答案 1 :(得分:1)
import itertools
nums = collections.Counter(itemlist)
target = t # the target sum
for i in range(len(itemlist)):
if itemlist[i] > target: continue
for j in range(i+1, len(itemlist)):
if itemlist[i]+itemlist[j] > target: continue
if target - (itemlist[i]+itemlist[j]) in nums - collections.Counter([itemlist[i], itemlist[j]]):
print("Found", itemlist[i], itemlist[j], target - (itemlist[i]+itemlist[j]))
答案 2 :(得分:0)
借用@ inspectorG4dget的代码,这有两个修改:
public IQueryable<ParkingLocation> GetParkingLocations()
{
return db.ParkingLocations
.Where(p => p.StartTime <= DateTime.Now.TimeOfDay && p.EndTime >= DateTime.Now.TimeOfDay);
}
那么我们就可以使循环短路。C < B
代替bisect_left()
。这似乎运行得更快。
collections.Counter()
为了减少比较次数,我们强制执行from random import randint
from bisect import bisect_left
X = randint(0, 2**32 - 1)
itemset = set(randint(0,X) for _ in range(100000))
itemlist = sorted(list(itemset)) # sort the list for binary search
l = len(itemlist)
for i,A in enumerate(itemlist):
for j in range(i+1, l): # use numbers above A
B = itemlist[j]
C = X - A - B # calculate C
if C <= B: continue
# see https://docs.python.org/2/library/bisect.html#searching-sorted-lists
i = bisect_left(itemlist, C)
if i != l and itemlist[i] == C:
print("Found", A, B, C)
。