O(N)中最长的子序列代码?

时间:2015-06-16 08:03:36

标签: python algorithm time-complexity longest-substring

有人问了我一个问题

Find the longest alphabetically increasing or equal string 
composed of those letters. Note that you are allowed to drop 
unused characters.

So ghaaawxyzijbbbklccc returns aaabbbccc.

Is an O(n) solution possible?

我实现了代码[在python中]

s = 'ghaaawxyzijbbbklccc'
lst = [[] for i in range(26)]

for ch in s:
    ml = 0
    for i in range(0,ord(ch) + 1 - ord('a')):
        if len(lst[i]) > len(lst[ml]):
            ml= i
    cpy = ''.join(lst[ml])
    lst[ord(ch) - ord('a')] = cpy + ch

ml = 0
for i in range(26):
    if len(lst[i]) > len(lst[ml]):
        ml = i
print lst[ml]

答案是'aaabbbcc'

我已经尝试了一些更多的例子和所有作品! 并且据我所知,这段代码的复杂性是O(N) 我们来举个例子 假设我有一个字符串'zzzz' 因此主循环将运行4次,内部循环将每次迭代运行26次,因此我们可以说在最坏的情况下代码将在

中运行
O(26*N + 26)
---------^-
this is the last iteration

所以O(N)是可以接受的吗?

现在问题是

  1. 是否适用于O(N)my code at ideone
  2. 如果它在O(N)中工作,那么为什么要使用DP of O(N2)code of DP
  3. 比代码Friends code
  4. 更好
  5. 此代码的限制

2 个答案:

答案 0 :(得分:2)

  1. 它是O(N)
  2. '为什么要使用DP of O(N2)' :你不需要解决这个问题。但是请注意,您利用了序列标记(字母)是有限的这一事实 - 因此您可以设置一个列表来保存所有可能的起始值(26),并且您只需要查找该列表中最长的成员 - O(1)操作。对于具有任意数量的有序标记的序列,可以在O(NlogN)中完成更多generalised solution
  3. 你朋友的代码基本相同,只是将字母映射到数字,26个起始位置的列表中包含26个字母数字 - 他们不需要做任何一个那些。但从概念上讲,这是一回事 - 持有一份清单。

    "更好的"是一个意见问题。虽然它具有相同的渐近复杂度,但是常数项可能不同,因此可以比另一个执行得更快。此外,就存储而言,可以使用比另一个更多的内存。如此低n - 判断哪个更具可读性可能比任一算法的绝对性能更重要。我不会做出判断。

    你可能会注意到"赢得"顺序是一个平局。例如 - 在您所在的测试字符串edxeducation上 - 您的实现返回ddin,而您的朋友返回ddio。两者似乎对我都有效 - 没有规则来打破这种关系。

  4. 此代码的主要限制是它只能处理在一个特定情况下完全由字母组成的序列。您可以扩展它以处理大写和小写字母,要么对它们进行相同的处理,要么使用所有小写字母为"小于"所有大写字母或类似的东西。这只是扩展它可以处理的有限令牌集。

    为了概括这个限制 - 代码只能处理有限的序列令牌集,如上面2所述。另外 - 没有错误处理,所以如果你输入一个带有数字或标点符号的字符串,它就会失败。

答案 1 :(得分:-1)

这是Longest Increasing Subsequence的变体。 不同之处在于,您的元素是有限的,因为它们只能来自' a'到了'。你的算法确实是O(N)。 O(N log N)是可能的,例如使用来自上面链接的算法。可能元素数量的界限将其转换为O(N)。