增长最快的独特子序列

时间:2015-11-18 11:09:09

标签: python arrays algorithm list sorting

我有一个列表/数组看起来像这样:

[ 0  1  2  3  4  5  6  7  3  9 10 11 13 13 14 15 16 17 18 19  4 16 22  5  3   
  2 10 17 34  5 11 18 27 14 11 15 29  2 11 10 19 32  8 27  1 32  6  2  0]

此列表假设是单调的(严格增加)。 它不是,但你可以看到它主要是增加。 不适合此模式的值可视为噪音, 我希望他们被删除 所以我想提取这个列表的最大可能子集 是一个严格增加的数字序列。 这里有许多可能的单调序列, 但关键是找到最大的一个。

重要的是我要删除要删除的值的索引, 因为我需要知道其余数字的确切位置 (因此,我们可以替换它们而不是删除数字 f.ex. Nonenan-1)。

我可以更改任何数字的顺序, 只需删除不适合的那些。

其余列表必须严格增加, 所以,如果我们有f.ex. <{1}}, 13个都必须删除。

如果有几种可能的解决方案同样大, 我们不能使用它们中的任何一个,必须选择一个数量少于1的解决方案。 F.ex.在[11 13 13 14],我们必须扔掉34和32, 因为我们不能选择一个而不是另一个。 如果我们有[27 29 30 34 32]则没有可能的解决方案, 因为我们无法在[27 29 34 15 32][27 29][27 34][29 34]之间进行选择。

上面列出的最佳解决方案是:

[15 32]

有人能想到一个可以执行此特定工作的算法吗? 如果你能让我参与其他方式,也会受到赞赏。

到目前为止我唯一的想法是循环[ 0 1 2 3 4 5 6 7 -1 9 10 11 -1 -1 14 15 16 17 18 19 -1 -1 22 -1 -1 -1 -1 -1 -1 -1 -1 -1 27 -1 -1 -1 29 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1] 其中for n in range(N, 0, -1):是列表的大小。 循环首先尝试找到大小为N的解, 然后是n=Nn=N-1等。 当它找到一个特定的n=N-2的解决方案时,它会停止并且 返回该解决方案。我还不确定循环内部应该是什么。

更新

另一个SO问题提供了一种用于查找最长的Python算法 列表的后续序列。这几乎就是我想做的,但并不完全。

我已经复制了该功能(见下文)并在最后添加了一些额外的代码 改变了输出n。 然后重建原始形状的原始序列, 但是不包括增加序列的一部分的数字被替换 由nans。然后我检查是否有任何数字出现过多次, 如果是这样,用nans替换所有出现的数字。

原始算法必须仍然可以更改,因为它没有提供 独特的解决方案。

例如:

if fullsize=True

给出

a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 32, 
    18, 19, 20, 16, 35, 35, 33, 32, 1, 35, 13, 5, 32, 8, 35, 29, 19, 
    35, 19, 28, 32, 18, 31, 13, 3, 32, 33, 35, 31, 0, 21]
print subsequence(a)

不应以[ 0. 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 32. nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan] 结尾,而应以#{1}结尾 .. 16 32 nan .., 据我所见。

更简单的例子:

... 16 nan ... nan 31 nan nan 32 33 35 nan nan nan]

给出

a = [0,1,2,3,4,1,2,3,4,5]
print subsequence(a)

但它应该只给出 [ 0. 1. 2. 3. nan nan nan nan nan 5.] 因为[0 nan ... nan 5]出现两次并且不是唯一的。

这是代码的当前半工作版本 (用于我的示例运行):

1 2 3 4

1 个答案:

答案 0 :(得分:2)

这是一个经典的动态编程问题。

为每个元素存储以该元素结尾的最大序列的长度。 对于第一个元素,值为1(只取该元素)。对于其余的,你取max(1,1 +分配给其他前一个元素的值是&lt; =然后你当前的元素)。

您可以使用2个循环(O(N ^ 2))来实现。如果您的数据非常大,可能会进行一些优化。或者知道你的序列大多数只是检查以前的X元素。

要修复数据,首先要指定一个最大值(最长单调序列的长度),然后用-1替换所有内容,然后在列表中向后查找序列中的前一个元素(应该是&lt; =然后当前的一个和指定的值应该是-1当前元素被分配的内容),而你没有找到匹配,该元素不属于。找到匹配项后,将其作为当前值并继续向后,直到找到一个已分配1的元素(这是第一个)。