效率优化

时间:2016-10-29 21:17:14

标签: python performance python-2.7

给定一个由-1到50个整数组成的列表,范围为-1000到1000,计算给定列表中一个或任意数量的整数的最大乘积。

我的方法:

import itertools

def answer(xs):
    cur = 1
    dal = []
    for i in range(len(xs), 0, -1):
        for j in itertools.combinations(xs, i):
            for x in j:
                cur *= x
            dal.append(cur)
            cur = 1
    dal.sort(reverse=True)
    return str(dal[0])

结果超时。我想优化程序的结构,使其尽可能高效。

4 个答案:

答案 0 :(得分:2)

除非你有几个月的计算时间,否则完成所有组合是一个坏主意。如果所有数字都是正数,那么你只需要将它们相乘。如果所有这些都是消极的你会采取其中的一些。如果你必须跳过一个,跳过最大值(-2大于-5)。向混合中添加零总是返回零,这比之前的任何情况都要糟糕。如果没有正数且零或一个负数,则只需取最大数字即可。它可以是零或唯一的负数。

def answer(xs):    
    mult = 1
    valid = 0

    for i in xs:
        if i > 0:
            mult *= i
            valid = 1

    negative = [i for i in xs if i<0]
    negative.sort()

    if(len(negative) & 1):
        del negative[-1]

    for i in negative:
            mult *= i
            valid = 1

    if valid==0:
        return max(xs)

    return mult

以下是一些测试用例:

xs =  [0]
print(xs,"->",answer(xs)) #[0] -> 0
xs =  [-1]
print(xs,"->",answer(xs)) #[-1] -> -1
xs =  [0,-1]
print(xs,"->",answer(xs)) #[0, -1] -> 0
xs =  [-2,-3]
print(xs,"->",answer(xs)) #[-2, -3] -> 6
xs =  [-2,-3,-4]
print(xs,"->",answer(xs)) #[-2, -3, -4] -> 12
xs =  [-2,-3,0]
print(xs,"->",answer(xs)) #[-2, -3, 0] -> 6
xs =  [-2,3]
print(xs,"->",answer(xs)) #[-2, 3] -> 3

答案 1 :(得分:0)

如果负数的计数为偶数,则可以通过乘以所有整数来实现最大乘积,否则最大乘积将离开负数(最接近零)并乘以所有其他乘积。 对于n = 1,按原样打印数字。

已编辑:

if len(mylist)==1:
    print mylist[0]
else:
    count=0
    for i in mylist:
        if i<0:
            count+=1
    if count>0:
        mylist.sort()
        if mylist[-1]==0:
            print "0"
        else:
            ans=1
            flag=1
            for i in xrange(len(mylist)):
                if mylist[i]>0 and flag==1:
                    ans/=mylist[i-1]
                else:
                    ans*=mylist[i]
            if flag==1:
                ans/=mylist[-1]
            print ans
    else:
        ans=1
        for i in mylist:
            if i>0:
                ans*=i
        print ans

然后从你的函数返回ans。

这是O(n)解决方案。

答案 2 :(得分:0)

这可以通过几种方式进行优化。首先,不是将所有内容托管在数组中,而是将变量maximum初始化为xs[0],并检查每个产品。此外,您可以使用operator模块中的mul而不是自己进行乘法运算。最后,我会在Python 2中使用xrange它不会创建一个数组,使其比range更高效。这将使您的代码看起来像这样

from itertools import combinations
from operator import mul    

def answer(xs):
    maximum = xs[0]
    one = 1 in xs
    filter(lambda a: a != 0 and a != 1, xs)
    if len(xs) == 0:
        if one:
            return 1
         else:
            return 0
    for i in xrange(len(xs), 0, -1):
        for j in combinations(xs, i):
            prod = reduce(mul, j, 1)
            if prod > maximum:
                maximum = prod
    return str(maximum)

我将报告保留为str(maximum),但您可以将其作为maximum返回,如果需要,可以返回整数。

答案 3 :(得分:0)

您可以对 O(n)时间复杂度使用两阶段算法。首先将所有正数相互乘以,如果没有正数,则选择最大数。使用reduce,可以通过一行轻松完成。

在以下步骤中过滤掉所有负数。如果不止一个将它们全部加在一起。如果乘法结果为负数(=其中有奇数的负数),则将结果除以负数的最大值。然后将步骤1中得到的产品与步骤2的产品相乘,得到最终结果。如果步骤1的产物是非正数,则结果是步骤2的产物。

from functools import reduce

nums = [3, -4, 5, -2, -3, 0, 1]
res = reduce(lambda x,y: x * y if x > 0 and y > 0 else max(x, y), nums)
negatives = [x for x in nums if x < 0]
if len(negatives) > 1:
    neg = reduce(lambda x,y: x * y, negatives)
    if neg < 0:
        neg //= max(negatives)
    res = max(res, 1) * neg

print(res)

输出:

180

如果您使用的是Python 2,则无需导入reduce,因为它是内置的而不是floordiv,只需使用常规的。{/ p>