我需要找到一个非常大的数组的所有连续子数组的所有可能的gcd。我需要的解决方案少于O(N 2 )时间。
这是我对O(N ^ 2)的解决方案。
from math import gcd
lst = [5,3,5,8,9,4,5,6] # A very long list
gcds = {1:0,2:0,3:0,4:0}# ..... All initialized with 0
for i in range(N):
g = lst[i]
for j in range(i+1,N):
g = gcd(g,lst[j])
if g== 1:
gcds[1] += N-j
break
gcds[j] += 1
答案 0 :(得分:1)
解决此问题的关键是GCD功能具有关联性。那是gcd(a, gcd(b, c)) == gcd(gcd(a, b), c)
确切有n(n+1)/2
个连续的子数组,每个子数组都有一个GCD,可以像通过简单地获取相邻元素的GCD,然后对三角形中每一行的结果重复此操作来计算它们:
5 3 5 8 9 4 5 6
1 1 1 1 1 1 1
1 1 1 1 1 1
1 1 1 1 1
1 1 1 1
1 1 1
1 1
1
from fractions import gcd
output = []
lst = [5,3,5,8,9,4,5,6]
while lst:
o = []
x = lst[0]
for l in lst[1:]:
o.append(gcd(l, x))
x = l
output.extend(o)
lst = o
print output
得到[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
个28
。
其复杂度为n(n+1)/2
或O(n ^ 2)。让我们忽略那个n=len(input)-1
。
这也适用于其他示例
3 6 9 4
3 3 1
3 1
1
该程序的结果为[3, 3, 1, 3, 1, 1]
使用Counter
,可以输出直方图而不是列表:
from fractions import gcd
from collections import Counter
output = []
gcds = Counter()
lst = [3, 6, 9, 4]
while lst:
o = []
x = lst[0]
for l in lst[1:]:
v = gcd(l, x)
gcds[v] += 1
o.append(v)
x = l
lst = o
print gcds
打印Counter({1: 3, 3: 3})