数组中索引的Python最长递增子序列

时间:2019-05-23 19:18:07

标签: python

此算法(最初在unl-aligner中实现)计算序列中相应编号递增的最长编号列表,因此给出

seq = [0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15]

它将返回

[0, 2, 6, 9, 11, 15]

实现看起来像

def subseq(seq, keyfn=lambda value: value):
    if not seq: return seq
    tail = []
    prev = []
    for i in range(len(seq)):
        for k in range(len(tail)-1, -1, -1):
            if keyfn(seq[tail[k]]) < keyfn(seq[i]):
                if len(tail) == k+1:
                    tail.append(i)
                elif keyfn(seq[tail[k+1]]) > keyfn(seq[i]):
                    tail[k+1] = i
                prev.append(tail[k])                    
                break
        else:
            tail.append(i)
            prev.append(None)

    i = tail[-1]
    subseq = [seq[i]]
    while prev[i] is not None:
        i = prev[i]
        subseq.append(seq[i])
    subseq.reverse()
    return subseq

该算法执行线性扫描,而二分法(二进制)搜索应为preferred。 重构它以执行二进制搜索的最佳方法是哪种?

1 个答案:

答案 0 :(得分:1)

使用this答案:

bisect = "longest_subsequence([1,2,3,4,5,6,7,2,2,2,2,2,5,1,7,8])"
_subseq = "subseq([1,2,3,4,5,6,7,2,2,2,2,2,5,1,7,8])"

from timeit import timeit

print(timeit(bisect, globals=globals(), number=10000))  # 0.2994734
print(timeit(_subseq, globals=globals(), number=10000))  # 0.32428109999999993

这是完全随机测试的结果,在您的示例中,它们似乎在时间上几乎是准确的