问题 :给定a[i](i=0...n-1),找到最长上升子序列(假设长度为k),输出k
例:
a = [4,2,4,5,3,7]
返回
k=4([2,4,5,7])
分析:
对于最优策略:一定有最后一个元素a[j]
情况1:最优策略就是{a[j]},长度k就是1
情况2:最优策略子序列长度大于1,则最优策略中最后一个元素a[j]前一定有一个元素a[i],且a[i]<a[j](i<j)
且以a[i]结尾的序列列也是最优的
子问题:f[i]表示以a[i]结尾的最长子序列长度
f[i] = max{1,f[i]+1 | i<j && a[i]<a[j] }
计算顺序:
f[0]...f[n-1]
时间复杂度O(n^2) ,空间复杂度O(n)
代码及注释如下:
def long_sequence(a):
#f[i]表示以a[i]结尾的上升子序列的长度
n = len(a)
if n == 0:
return ;
f = [0 for j in range(n)]
#初始,以a[0]结尾的最长上升子序列长度就是1
for j in range(n):
#情况1,f[0] = 1
f[j] = 1
#枚举j之前最优子序列长度
for i in range(j):
if a[i] < a[j] and f[j] < f[i]+1:
f[j] = f[i] + 1
return max(f)
a = [4,2,4,5,3,7]
print(long_sequence(a))
#结果:4
信封问题跟这个类似,就放一起比较
问题:给定N个信封的长和宽,如果另一个信封的长和宽更小,则可以被套进信封去,问,最多嵌套多少个信封?
分析:
确定状态:
先考虑长度,将所有信封长度从小到大排序
设:最优策略里最外层信封的长度时Ej,则
次外层信封的长度Ei,也是最优策略,且Ei<Ej(i<j)
子问题:要知道以Ej结尾的最优策略的长度,则我们需要知道以Ei结尾的最优策略
设f[i]是以Ei为最外层信封的最优策略的信封数
f[i] = max{i, f[j] + 1 | Ej在Ei里,j<i}
无初始条件
依次求f[0],...,f[n-1]
需要对信封长度排序,时间复杂度O(N^2),空间复杂度O(N)
代码及注释如下:
def doll_envelope(E):
n = len(E)
if n == 0:
return 0
#f[i]是以Ei为最外层信封的最优策略的信封数
f = [0 for i in range(n)]
for i in range(n):
#f[0] = 1
f[i] = 1
for j in range(i):
#前面的长度小且宽度小,信封j可以放到信封i里
if E[j][0] < E[i][0] and E[j][1] < E[i][1]:
f[i] = max(f[i],f[j] + 1)
return max(f)
A = [[5,4],[6,4],[6,7],[2,3]]
E = sorted(A)
print(doll_envelope(E))
#结果:3
未完待续。。。