【问题标题】:Number of ways such that sum of k elements equal to p使 k 个元素之和等于 p 的方式数
【发布时间】:2016-09-09 03:39:09
【问题描述】:

给定一系列整数,其中一个数字等于前两个数字的总和,起始整数为 1

系列 ->1,2,3,5,8,13,21,34,55

找出使k个元素之和等于p的方法的数量。我们可以使用一个元素任意次数。

p=8

k=4。

所以,方法的数量是 4。这些是,

1,1,1,5

1,1,3,3

1,2,2,3

2,2,2,2

我可以通过递归来解决这个问题。我在这里感觉到动态编程,但我不知道该怎么做。可以在更短的时间内完成吗???

编辑我忘了说数字的顺序无关紧要,只会计算一次。对于 ex=3->(1,2)and(2,1).here 的方式数仅为 1。

【问题讨论】:

  • 同一个老师还是网络竞赛? stackoverflow.com/questions/37193565
  • 这是一个在线法官的问题。我前几天看到了,但我不记得它是从哪里来的。
  • @warrior,输入序列是斐波那契数列吗?
  • @vish4071 是的,输入是斐波那契数列
  • 输入p可以是什么? (并不总是斐波那契数)...这个例子有点误导

标签: arrays algorithm recursion dynamic-programming


【解决方案1】:

编辑:自发布以来,海报已更改原始问题。我的算法仍然有效,但也许可以改进。原始问题有 n 个任意输入数字(他现在已将其修改为斐波那契数列)。要将我的算法应用于修改后的帖子,请通过仅取小于 p 的元素来截断系列(假设其中有 n 个)。

这是一个n^(k/2) 算法。 (n是系列中的元素个数)

使用长度为p 的表,这样table[i] 包含所有k/2 元素的组合,总和为i。例如,在您提供的示例数据中,table[4] 包含{1,3}{2,2}

编辑:如果空间太大,同样的算法可以用有序链表完成,你只存储非空表条目。链表必须是双向的:向前和向后,这使得算法的最后一步更清晰。

计算完此表后,只要两者都不为空,我们就会通过将每个 table[j] 与每个 table[p-j] 组合来获得所有解决方案。

要获取表,请将整个事物初始化为空。那么:

For i_1 = 0 to n-1:
    For i_2 = i_1 to n-1:
        ...
            For i_k/2 = i_k/2-1 to n-1:
                sum = series[i_1] + ... + series[i_k/2]
                    if sum <= p:
                        store {i_1, i_2, ... , i_k/2 } in table[sum]

这种“可变数量的循环”看起来不可能实现,但实际上它可以通过一个长度为 k/2 的数组来完成,该数组跟踪每个 i_` 的位置。

让我们回到您的数据,看看我们的表格会是什么样子:

table[2] = {1,1}
table[3] = {1,2}
table[4] = {1,3} and {2,2}
table[5] = {2,3}
table[6] = {1,5}
table[7] = {2,5}
table[8] = {3,5}

通过将table[2]table[6]table[3]table[5] 以及table[4]table[4] 组合来找到解决方案。因此,解决方案是:{1,1,1,5} {1,2,2,3}, {1,1,3,3}, {2,2,2,2}, {1,3,2 ,2}。

【讨论】:

  • 这里的 p 可以大到 10^9。不可能创建这样大小的数组。
  • @warrior:查看我的编辑。我的算法仍然可以处理这么大的尺寸而不会爆炸。
  • 因为它是一个在线判断问题,内存不足以满足您的算法
  • @warrior,如果你使用链表,你同意内存要求是 n^(k/2) 吗?你说这是不是太过分了?我现在要说的是,这将比任何动态编程解决方案使用得更少。
【解决方案2】:

您可以使用动态编程。设C(p, k) 是等于pk 元素和a 是元素数组的方式数。那么

 C(p, k) = C(p - a[0], k - 1) + C(p - a[1], k - 1) + .... + C(p - a[n-1], k - 1)

然后,您可以使用记忆来加速您的代码。

【讨论】:

  • 是的,我知道这一点。但是因为 p 可以达到 10^9,所以这个解决方案似乎效率不高。我们可以加快速度吗。我们可以利用给定的系列或 k= 的最大值10.
  • @warrior,它是高效的,因为最重要的不是 p 有多大。这是关于k有多大。 k 将确定递归的深度。由于 k 仅低于 10。
  • @invisal 您能否在您的帖子中包含运行时间分析?
  • @TheGreatContini,没有记忆就n^k了。
  • @invisal 我忘了说数字的顺序无关紧要,只会计算一次。对于 ex=3->(1,2)and(2,1).here 方法的数量只有 1。你能告诉我在这个递归公式中要改变什么来处理这种情况吗?
【解决方案3】:

提示:

您的问题众所周知。它是和集问题,是背包问题的变体。检查这个很好的解释。 sum-set problem

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-01-12
    • 1970-01-01
    • 1970-01-01
    • 2019-08-13
    • 2016-02-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多