【问题标题】:How can I generate all possible sums in the following sequence?如何按以下顺序生成所有可能的总和?
【发布时间】:2016-09-26 11:24:25
【问题描述】:

假设我有一个数组,可以说 [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

我只想要 所有这些值的总和的最终总和,而不是实际的组。我该怎么做?

我能够通过首先生成所有可能的组然后找到总和来做到这一点

但是因为我只需要总和而不需要实际的组,有没有更好的方法

【问题讨论】:

  • stackoverflow.com/questions/22915726/… 在这里是相关的。我怀疑这可以在 O(N) 时间内完成。
  • 可能有这种可能性,但这取决于您的数组是否已解决问题(就其中的元素数量而言),或者您是否想为任意数组构建函数。是什么情况?
  • 我不确定我是否完全理解你的意思....在问题中,我们将得到一个数组(任意长度)及其元素,并且需要找到上述的总和
  • 好吧,如果我的想法可以有任何长度,那我的想法就行不通了。
  • 你还能在 cmets 中说出你的想法吗

标签: python-3.x dynamic-programming


【解决方案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,并且 sum(L[a:b]) 为 S[b] - S[a]。

【讨论】:

  • 我只想要最终的总和,即所有可能组的总和
  • 我的朋友(给我这个问题的人)声称它也可以在 O(n) 内完成!!
  • 这实际上是 O(n^3) 因为对 sum(L[i:k]) 的重复调用,但它可以通过使用 DP 降低到 O(n^2),构建一个总和表,用于计算 O(1) 中的每个总和。您使用 S[i] = S[i-1] + L[i] 构建一个数组 S,并且 sum(L[a:b]) 为 S[b] - S[a]。但要将其降低到 O(n),我必须考虑更多......
  • @rjmessibarca 是的,既然你提到了它。这似乎是可能的。您构建项 (1+2+3+4+5)*5 = 1*2 + 2*5 + 3*5 + 4*5 + 5*5。你打破所有的项目并对每个数字只求和一次,计算它出现了多少次。对于 1 是 1*1*16 + 1*2*8 + 1*3*4 + 1*4*2 + 1*5*1 + 1*6*1,对于 2 是 2*1*8 + 2* 2*4 + 2*3*2 + 2*4*1 + 2*5*1。
猜你喜欢
  • 1970-01-01
  • 2017-09-09
  • 2023-02-20
  • 1970-01-01
  • 2013-06-28
  • 1970-01-01
  • 2021-12-27
  • 1970-01-01
相关资源
最近更新 更多