我需要按n
整数的顺序找到子序列的最大乘积。我正在寻找一种算法,不一定表示为代码。
示例:
我已在O(n²)
中完成了算法,但现在我需要O(n)
中的算法
我知道这是可能的。
如何在O(n)
?
答案 0 :(得分:5)
如果您的所有输入都是> 0,通过将所有数字相乘得到最大乘积。
如果您的所有输入都是非0并且偶数均为负数,则再次通过将所有数字相乘来找到最大乘积。
因此,工作是处理零和负数。
您需要通过列表一次,随时计算正在运行的产品。 如果你达到0,那么之前的所有内容都是一个候选子集,如果它比迄今为止发现的最好,那么需要保存其详细信息(起始索引,结束索引,产品)。现在开始一个新的运行产品。 如果您达到负数,则该项是您的总计中的条件中断。 不使用负数的运行产品将被评估为最佳状态。但是现在你需要有2个正在运行的产品,一个是负数而另一个是新产品。因此,后续乘法需要对2个列表起作用。此时我将有2个正在运行的产品。如果你打另一个负数,你的每个运行列表都需要按照之前的描述进行二分。如果你不修剪,你可能会得到很多运行列表。我认为你可以修剪运行列表只跟踪3:刚启动的子列表,带有奇数负数的连续列表和偶数奇数的负数。任何候选子列表都不是正在进行的乘法的一部分,应该在放弃它之前评估它是最好的。
最后是O(n)
答案 1 :(得分:2)
一组非零数字的最大子序列乘积是所有数字的乘积(如果有偶数个负数),或者它是第一个负数后所有数字的乘积中的较大者,以及所有数字的乘积,直至最后一个负数。
这为您提供了O(N)解决方案:将序列分解为非零数字的运行,并将第一段中的规则应用于每个。选择最大值。
类似C的Python代码:
def prod(seq, a, b):
r = 1
for i in xrange(a, b):
r *= seq[i]
return r
def maxprodnon0(seq, a, b):
firstneg = -1
negs = 0
for i in xrange(a, b):
if seq[i] >= 0: continue
negs += 1
if firstneg < 0:
firstneg = i
lastneg = i
if negs % 2 == 0: return prod(seq, a, b)
return max(prod(seq, firstneg + 1, b), prod(seq, a, lastneg))
def maxprod(seq):
best = 0
N = len(seq)
i = 0
while i < N:
while i < N and seq[i] == 0:
i += 1
j = i
while j < N and seq[j] != 0:
j += 1
best = max(best, maxprodnon0(seq, i, j))
i = j
return best
for case in [2,5,-1,-2,-4], [1,2,0,-4,5,6,0,7,1], [1,2,0,-4,5,6,-1,-1,0,7,1]:
print maxprod(case)