假设我有一个数组,可以说[1,2,3,4]:
我想找到如下总和:
首先我生成像:
这样的对(1 2 3 4)
(123)(4)
(1)(234)
(12)(34)
(12)(3)(4)
(1)(23)(4)
(1)(2)(34)
(1)(2)(3)(4)
然后,ans将是一个组中元素的总和乘以该组的长度(对于所有可能的组)
例如,在安排(123)(4)中,总和将是(1+2+3)*3 + (4)*1
我只想要最终总和,它是所有这些值的总和,而不是实际的组。我怎么能这样做?
我能够通过首先生成所有可能的组然后找到总和
来实现但是因为我只需要总和而不是实际的群体,是否有更好的方法?
答案 0 :(得分:1)
安排数量为2**(len(L)-1)
。 8个元素的列表产生128种不同的排列。这是一个指数问题。您可以生成所有可能的解决方案,然后计算每个答案,或者您可以动态计算每个答案。无论哪种方式,它仍然是exp。
def part1(L, start, lsum):
if start == len(L):
print lsum
else:
for i in range(start, len(L)):
left = sum(L[start:i+1]) * (i-start+1)
part1(L, i + 1, lsum + left)
def part2(L, M, X, start):
if start == len(L):
M.append(X)
print sum([sum(x) * len(x) for x in X])
else:
for i in range(start, len(L)):
part2(L, M, X + [L[start:i+1]], i + 1)
例如:
>>> part1(L, 0, 0)
10
17
15
28
13
20
22
40
>>> M = []
>>> part2(L, M, [], 0)
10
17
15
28
13
20
22
40
编辑:O(n ** 3)
中所有总和的总和对于L = [1,2,3,4,5,6]
[[[1], [2], [3], [4], [5], [6]],
[[1], [2], [3], [4], [5, 6]],
[[1], [2], [3], [4, 5], [6]],
[[1], [2], [3], [4, 5, 6]],
[[1], [2], [3, 4], [5], [6]],
[[1], [2], [3, 4], [5, 6]],
[[1], [2], [3, 4, 5], [6]],
[[1], [2], [3, 4, 5, 6]],
[[1], [2, 3], [4], [5], [6]],
[[1], [2, 3], [4], [5, 6]],
[[1], [2, 3], [4, 5], [6]],
[[1], [2, 3], [4, 5, 6]],
[[1], [2, 3, 4], [5], [6]],
[[1], [2, 3, 4], [5, 6]],
[[1], [2, 3, 4, 5], [6]],
[[1], [2, 3, 4, 5, 6]],
[[1, 2], [3], [4], [5], [6]],
[[1, 2], [3], [4], [5, 6]],
[[1, 2], [3], [4, 5], [6]],
[[1, 2], [3], [4, 5, 6]],
[[1, 2], [3, 4], [5], [6]],
[[1, 2], [3, 4], [5, 6]],
[[1, 2], [3, 4, 5], [6]],
[[1, 2], [3, 4, 5, 6]],
[[1, 2, 3], [4], [5], [6]],
[[1, 2, 3], [4], [5, 6]],
[[1, 2, 3], [4, 5], [6]],
[[1, 2, 3], [4, 5, 6]],
[[1, 2, 3, 4], [5], [6]],
[[1, 2, 3, 4], [5, 6]],
[[1, 2, 3, 4, 5], [6]],
[[1, 2, 3, 4, 5, 6]]]
似乎有一种模式。奇怪的情况是:将序列的第一个元素作为最小元素的集合作为有序集合,有32个。但是其余的全部都是16.对于列表的每个元素,我添加包含的所有集合该元素作为第一个排序元素。
def part3(L):
ret = 0
for i in range(len(L)):
p = 0
for k in range(len(L) - i - 1):
p += sum(L[i:i+k+1]) * (k+1) * 2**(len(L) - i - k - 2)
p += sum(L[i:]) * (len(L) - i)
ret += p * max(1, 2**(i-1))
return ret
edit2:将它降低到O(n ^ 2)你需要使用DP。建立一个总和表来计算O(1)中的每个总和。使用S [i] = S [i-1] + L [i]构建数组S,求和(L [a:b])为S [b] - S [a]。