我有两个由数字组成的列表(整数);两者都有200万个独特的元素。
我想从列表1中找到数字a,从列表2中找到b,即 -
1)a*b should be maximized.
2)a*b has to be smaller than certain limit.
这是我想出的:
maxpq = 0
nums = sorted(nums, reverse=True)
nums2 = sorted(nums2, reverse=True)
for p in nums:
n = p*dropwhile(lambda q: p*q>sqr, nums2).next()
if n>maxpq:
maxpq=n
print maxpq
有什么建议吗? 编辑:我的方法太慢了。这将需要一天以上。
答案 0 :(得分:4)
这是线性时间解决方案(排序后):
def maximize(a, b, lim):
a.sort(reverse=True)
b.sort()
found = False
best = 0
j = 0
for i in xrange(len(a)):
while j < len(b) and a[i] * b[j] < lim:
found = True
if a[i]*b[j] > best:
best, n1, n2 = a[i] * b[j], a[i], b[j]
j += 1
return found and (best, n1, n2)
简单地说:
这样,您可以保证只查看每个列表一次。如果它找不到足够小的东西,它将返回False
,否则它将返回产品和产生它的对。
示例输出:
a = [2, 5, 4, 3, 6]
b = [8, 1, 5, 4]
maximize(a, b, 2) # False
maximize(a, b, 3) # (2, 2, 1)
maximize(a, b, 10) # (8, 2, 4)
maximize(a, b, 100) # (48, 6, 8)
答案 1 :(得分:1)
感谢大家的建议和想法。我终于找到了有用的解决方案。检查员G4dget先生对这一点有所了解。
它使用python标准库中的bisect
模块。
edit:bisect模块执行二进制搜索,以便在排序列表中查找值的插入位置。因此,与以前的解决方案不同,它减少了比较次数。
http://www.sparknotes.com/cs/searching/binarysearch/section1.rhtml
import bisect
def bisect_find(num1, num2, limit):
num1.sort()
max_ab = 0
for a in num2:
complement = limit / float(a)
b = num1[bisect.bisect(num1, complement)-1]
if limit > a*b > max_ab:
max_ab=b*a
return max_ab
答案 2 :(得分:0)
这可能会更快。
def doer(L1, L2, ceil):
max_c = ceil - 1
L1.sort(reverse=True)
L2.sort(reverse=True)
big_a = big_b = big_c = 0
for a in L1:
for b in L2:
c = a * b
if c == max_c:
return a, b
elif max_c > c > big_c:
big_a = a
big_b = b
big_c = c
return big_a, big_b
print doer([1, 3, 5, 10], [8, 7, 3, 6], 60)
请注意,它会对列表进行排序;这种情况更快,但可能适用于您的情况,也可能不适用。