# 采用贪心法+二分法。使用maxlen存储对应元素的最大递增序列长度;tmp存储实际值
# 概念1:当新加入的元素i比末尾元素大时,满足递增---直接加入; 若比末尾元素小,则
# 采用二分法寻找第一个比该元素大的数,并将其替换为i
# 以[2,1,5,3,6,4,8,9,7]为例。最初mexlen=[1];tmp=[2].
# 加入1,比tmp[-1]小,因此将2替换为1---tmp=[1],maxlen=[1,1]
# 加入5,比tmp[-1]大,直接加入---tmp=[1,5],maxlen=[1,1,2]
# 加入3,比tmp[-1]小,因此将5替换为3---tmp=[1,3],maxlen=[1,1,2,2]....
# 最后tmp=[1,3,4,7,9]; maxlen=[1,1,2,2,3,3,4,5,4]
# 概念2:len(tmp)表示最大长度,但是并不一定是最终值。len(maxlen)表示arr的长度
# maxlen[-2]=5,表示对应的arr[-2]是最大递增序列的末尾,同理maxlen[-3]=4,表示
# 对用的arr[-3]为倒数第二位; 1,2,2,2是因为有很多种组合,字典序按最小排列,故去最前方的值
class Solution:
def LIS(self , arr ):
if len(arr)<2: return arr
self.index=None #构建二分查找,查找第一个比i大的元素位置
def binary_find(arr,left,right,target):
if left>right: return
mid=int(left+(right-left)/2)
if arr[mid]>=target: #注意>=,因为可能存在4,4
self.index=mid
return binary_find(arr, left, mid-1, target)
elif arr[mid]<target:
return binary_find(arr, mid+1, right, target)
maxlen,tmp=[1],[arr[0]]
for i in arr[1:]:
if i>tmp[-1]:
tmp.append(i)
maxlen.append(len(tmp))
else:
binary_find(tmp,0, len(tmp)-1, i)
tmp[self.index]=i
maxlen.append(len(tmp[:self.index+1]))
length=len(tmp) #实际的最大长度
for i in range(len(arr)-1,-1,-1):
if maxlen[i]==length:
tmp[length-1]=arr[i]
length-=1
return tmp
# write code here