从所有子集中恢复原始数组

时间:2018-06-03 05:28:40

标签: arrays algorithm subset

您将获得数组的所有子集和。然后,您应该从提供的子集中恢复原始数组。

原始数组中的每个元素都保证是非负数且小于10 ^ 5。原始数组中的元素不超过20个。原始数组也已排序。输入保证有效。

示例1

如果提供的子集总和是:

0 1 5 6 6 7 11 12

我们可以很快推断原始数组的大小是3,因为有8(2 ^ 3)个子集。上述输入的输出(即原始数组)是:

1 5 6

示例2

输入:

0 1 1 2 8 9 9 10

输出:

1 1 8

我尝试过什么

由于所有元素都保证是非负的,因此输入中的最大整数必须是数组的总和。但是,我不知道如何从那里开始。根据逻辑,我认为下一个(2 ^ 2 - 1)个最大的子集和必须包括除数组中的一个元素以外的所有子集。

但是,当原始数组为:

时,上述逻辑不起作用
1 1 8

这就是为什么我被困住了,我不确定如何继续。

2 个答案:

答案 0 :(得分:1)

Say S是子集sum数组,A是原始数组。我假设S已经分类了。

|A| = log2(|S|)
S[0] = 0
S[1] = A[0]
S[2] = A[1]
S[3] = EITHER A[2] OR A[0] + A[1].

通常,对于i> = 3的S [i]是A的元素或者您已经遇到的A的元素的组合。处理S时,每生成一个A的已知元素组合跳过一次,生成给定数字,将任何剩余数字添加到A.当A达到正确大小时停止。

例如,如果A = [1,2,7,8,9]则S将包括[1,2,1 + 2 = 3,...,1 + 8 = 9,2 + 7 = 9, 9,...]。当处理S时,由于1 + 8和2 + 7,我们跳过两个9,然后看到我们知道必须属于A的第三个9。

例如,如果S = [0,1,1,2,8,9,9,10],那么我们知道A有3个元素,A的前2个元素是[1,1],当我们得到到2我们跳过它因为1 + 1 = 2,我们追加8并且我们已经完成因为我们有3个元素。

答案 1 :(得分:0)

这是一个简单的算法,不需要找到给定数字的哪个子集和。

S←输入序列
X←空序列

虽然S有一个非零元素:

  1. d←S的第二个最小元素(最小的一个总是为零)
  2. 在X
  3. 中插入d
  4. N←空序列
  5. 虽然S不是空的:
    • z←S
    • 的最小元素
    • 从S中删除z和z + d(如果S不包含z + d,则表示错误;如果有多个,则只删除z和z + d的一个实例)。
    • 在N中插入z。
  6. S←N
  7. 输出X。