300. 最长递增子序列

一、题目

给你一个整数数组 nums ,找到其中最长严格递增子序列的长度。

子序列 是由数组派生而来的序列,删除(或不删除)数组中的元素而不改变其余元素的顺序。例如,[3,6,2,7] 是数组 [0,3,1,6,2,2,7] 的子序列。

二、思路

dp[i]: 所有长度为i+1的递增子序列中, 最小的那个序列尾数. 由定义知dp数组必然是一个递增数组 依次判断每个数num将其插入dp数组相应的位置: 1. num > dp[-1], ,执行插入尾部操作,表示num比所有已知递增序列的尾数都大, 将num添加入dp 数组尾部 2. num <= dp [-1],则执行替换操作,【1,2,4,5】 现在来了一个3,那么替换为【1,2,3,5】,而不是【1,3, 4,5】

三、代码

class Solution:
    def lengthOfLIS(self, nums):
        n = len(nums)
        if n <= 1: # 不要忘了空数组
            return n
        stack = [nums[0]]  # 初始时候,只有一个元素,那么它肯定是递增的,所以加入
        for i in range(1,n):
            if nums[i] > stack[-1]:
                stack.append(nums[i])
            else:
                # 不会动递增序列的个数,但是会调整递增序列的值,这儿也可以用二分查找
                for j in range(len(stack)):
                    # dp=【1,2,4】 ,nums[i]=3
                    if nums[i] > stack[j]:
                        continue
                    else:
                        stack[j] = nums[i] # 将数组中的值替换
                        break
        return len(stack) # 返回递增序列的长度,就是最长递增子序列

四、分析

复杂度分析

  • 时间复杂度:O(n2),其中 n 为数组 nums 的长度。动态规划的状态数为 n,计算状态 dp[i] 时,需要 O(n) 的时间遍历 dp[0…i−1] 的所有状态,所以总时间复杂度为 O(n2)

  • 空间复杂度:O(n),需要额外使用长度为 n 的 dp 数组。

 

posted @ 2023-04-05 21:43  ImreW  阅读(10)  评论(0编辑  收藏  举报