题目
输入: [10,9,2,5,3,7,101,18]
输出: 4
解释: 最长的上升子序列是 [2,3,7,101],它的长度是 4。
1.基础动态规划方法
1.定义cell保存每个位置的最大序列长度
2.在当前位置往前找小于当前位置数值的数,更新cell
class Solution:
def lengthOfLIS(self, nums: List[int]) -> int:
if nums == []:
return 0
cell = [1]
for i in range(1,len(nums)):
cell.append(1)
for j in range(i):
if(nums[j] < nums[i]):
cell[i] = max(cell[i], cell[j]+1)
return max(cell)
流程见下图:
这种方法需要重复遍历每个位置之前的数据。。时间复杂度O(n^2)
2.动态规划+二叉搜索
1.遍历到每个位置都保存当前的最长序列dp
2.遍历下一个位置的时候如果比dp[-1]的值大,直接append到dp中,否则二叉判断其dp中的位置,把dp中该位置的值换成当遍历的数
3.dp中的值可能不是真实的上升序列,但是长度是对的
a = [10,6,4,0,3,1,9,10]
class Solution:
def lengthOfLIS(self, nums):
if len(nums) < 2:
return len(nums)
dp = [nums[0]]
for num in nums[1:]:
if dp[-1] < num:
dp.append(num)
continue
l,r = 0,len(dp)-1
while l<r:
mid = (l + r) // 2
if dp[mid] < num:
l = mid + 1
else:
r = mid
dp[l] = num
return len(dp)
s = Solution()
s.lengthOfLIS(a)
流程:
这种方法相当于不断的把较小的值往dp中去排,越小的值越可能组成递增序列,是一种比较巧的方法,时间复杂度O(nlog(n))。