最长单调递增子序列

来自十五章动态规划两个练习题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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值