来自十五章动态规划两个练习题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=0n[O(lgL)+O(1)]=O(nlgn)