最长单调递增子序列

来源:互联网 发布:网络小精灵粤语 编辑:程序博客网 时间:2024/06/05 02:28

来自十五章动态规划两个练习题15.4-5 15.4-6

O(n2)算法

初步的方法是O(n2)的算法。God Xu 指点我:
- 令Y = sort(X)
- 求X、Y的最长公共子序列

O(nlgn)算法

下一题要求用O(nlgn) 时间的算法,经过查阅资料, 得到如下算法:

__author__ = 'burger'#用二分搜索找最大小于_target的位置def binary_search(_M, _X, _lo, _hi, _target):    if _lo > _hi:        return max(_hi, 0)    mid = (_lo + _hi)//2    if _X[_M[mid]] > _target:        return binary_search(_M,_X, _lo, mid - 1, _target)    elif _X[_M[mid]] < _target:        return binary_search(_M, _X,  mid + 1,_hi, _target)    else:        return max(mid - 1,0)def longest_monotonically_increasing_subsequence(_X):    L = 1    n = len(_X)    M = [0]    P = [0]*n    for i in range(1,n):        j = binary_search(M, _X, 0, L - 1 , _X[i])        P[i] = M[j]  #_X的前驱是M[j]        if j + 1 == L: #子序列变长            M.append(i )        elif _X[M[j + 1]] > _X[i]:  #更新j长度的最长子序列位置            M[j + 1] = i        L = max(L, j+2)  # 更新子序列长度,如果j+1是L,那么子序列就变长一个,变成j+2    return M,P#递归打印def print_lmis(_X, _p, _n):    if _n == 0:        print(_X[_n])    else:        print_lmis(_X, _p, _p[_n])        print(_X[_n])if __name__ == '__main__':    X = [0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15]    m,p = longest_monotonically_increasing_subsequence(X)    print_lmis(X, p, len(X) - 1)

复杂度分析:

Binary search: O(lgL), 共进行n次,worst case L from 0 to n,

L=0n[O(lgL)+O(1)]=O(nlgn)

0 0