参考博客:寻找数组中最大递增子序列
#coding=utf-8
# 寻找list中的最长递增子序列.. 不要求元素必须彼此相邻.. 如:[1,-1,2,-3,4,-5,6,-7] >> [1,2,4,6]
# https://wax8280.github.io/2016/10/18/859/
# 这段代码我真是看了很久都还没完全吃透理解...
def getdp(arr):
n = len(arr)
# dp存储到当前位置i为止的,最长递增子序列长度..
# end存储当前最大递增子序列最大元素,的最小值 MaxV
dp, ends = [0] * n, [0] * n
ends[0], dp[0] = arr[0], 1
right = 0
for i in range(1, n):
l = 0
r = right # end[0,...right]
# 二分查找,找到当前的s[i]是否是可以比前i-1个中的某个值大.
# 若找不到,则更新ends[l或r]
# 若arr[i]比ends有效区的值都大,则l=right+1
# s = [2, 1, 5, 3, 6, 4, 8, 9, 7]
while l <= r:
m = (l + r) / 2 # 二分查找使更快..
if arr[i] > ends[m]: # 这是没找到end大于a[i]的情况,则继续二分查找..
l = m + 1
else:
r = m - 1
# while循环是直到l>r才退出的..
right = max(right, l)
ends[l] = arr[i] #
dp[i] = l + 1
return dp
def generateLIS(arr, dp):
n = max(dp)
index = dp.index(n)
lis = [0] * n
n -= 1
lis[n] = arr[index]
# 从右向左
for i in range(index, 0 - 1, -1):
# 关键
if arr[i] < arr[index] and dp[i] == dp[index] - 1:
n -= 1
lis[n] = arr[i]
index = i
return lis
s = [2, 1, 5, 3, -1, 4, 3, -3, -2]
dp = getdp(s)
print '方法一##############', max(dp)
res = generateLIS(s, dp)
print res
######################### my code1 #############################
# 时间复杂度O(N^2)..
# 效率最低的...
def fun(s):
n = len(s)
LIS = [1] * n
for i in range(n):
for j in range(i): # j,遍历当前的最大递增子序列
if s[i] > s[j] and LIS[j] + 1 > LIS[i]:
LIS[i] = LIS[j] + 1
return max(LIS)
s = [2, 1, 5, 3, -1, 4, 3, -3, -2]
res1 = fun(s)
print '方法二#############', res1
######################### my code2 #############################
def fun2(s):
n = len(s)
LIS = [1] * n # 存放每个i位置的最长子序列值
Maxv = [1] * (n + 1) # 存放最长子序列内的最大值
Maxv[1] = 1
Maxv[0] = min(s) - 1 # 取边界?
maxlen = 1 # 最大的递增子序列长度
for i in range(1, n):
# j是遍历当前最大的递增子序列长度
for j in range(maxlen, -1, -1): # 这里需要逆序注意!!!
if s[i] > Maxv[j]: # 找到了现在进来的这个s[i]比哪一个长度的j对应的Maxv值大,那么LIS[i]就是j+1
LIS[i] = j + 1
break # 找打了就可以马上break了,不需要再遍历更前面的Maxv值..
if LIS[i] > maxlen:
maxlen = LIS[i]
Maxv[LIS[i]] = s[i]
# 这个else是因为s[i]进来没能LIS[I]大于maxlen,即可能s[i]找到的大于的Maxv[j]j是比较靠中间的j,所以它是存在Maxv[j + 1]的
# 所以如果Maxv[j + 1]更大s[i]更小,那么s[i]可以替换掉Maxv[j + 1]
elif Maxv[j] < s[i] and s[i] < Maxv[j + 1]:
Maxv[j + 1] = s[i]
return maxlen
s = [2, 1, 5, 3, -1, 4, 3, -3, -2]
res2 = fun2(s)
print '方法三###############'
方法以一直还是没吃透。。。
放上来希望有大神能愿意指点一二。。。~~