2 lists, and finding maximum product from 2 lists

I have two lists made of numbers(integers); both have 2 million unique elements.

I want to find number a from list 1 and b from list 2, that -

1)a*b should be maximized.
2)a*b has to be smaller than certain limit.

here's what I came up with:

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

any suggestions? edit : my method is too slow. It would take more than one day.


Here's a linear-time solution (after sorting):

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)

Simply put:

  • start from the highest and lowest from each list
  • while their product is less than the target, advance the small-item
  • once the product becomes bigger than your goal, advance the big-item until it goes below again
  • This way, you're guaranteed to go through each list only once. It'll return False if it couldn't find anything small enough, otherwise it'll return the product and the pair that produced it.

    Sample output:

    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)
    

    Thanks for everyone's advices and ideas. I finally came up with useful solution. Mr inspectorG4dget shone a light on this one.

    It uses bisect module from python's standard library.

    edit : bisect module does binary search in order to find insert position of a value in a sorted list. therefore It reduces number of compares, unlike my previous solution.

    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
    

    This might be faster.

    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)
    

    Note that it sorts the lists in-place; this is faster, but may or may not be appropriate in your scenario.

    链接地址: http://www.djcxy.com/p/66262.html

    上一篇: CasperJS getElementsByXPath只返回第一个元素

    下一篇: 2列表,并从2个列表中查找最大产品