题目

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

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

示例:
输入:nums = [10,9,2,5,3,7,101,18]
输出:4
解释:最长递增子序列是 [2,3,7,101],因此长度为 4 。

思路分析

这道题求最长上升子序列,我们可以定义一个 dp 数组,dp[i] 表示以 nums[i] 为最后一个元素时,最长上升子序列的长度,要想知道 dp[i],我们必然要先从 0 ~ i - 1 元素中,查找到所有数值小于当前 nums[i] 的元素。然后再在这些元素中,找到最长上升子序列长度最大的元素nums[j],而我们要求的 dp[i] 就等于 dp[j] + 1。其过程如下所示:

1、首先 dp[0] 默认等于 1,尽管只有一位,也是需要自立门户,长度为1的。

2、接下来要获得 dp[1] 的值,nums[1] 在其前面没有找到比自己小的元素,因此只能自立门户,dp[1] = 1。

java 动态规划 最长递增子序列 leetcode 最长递增子序列_数组

3、接下来要获得 dp[2] 的值,nums[2] 在前面依旧没有找到比自己小的值,仍然自立门户,dp[2] = 1。

java 动态规划 最长递增子序列 leetcode 最长递增子序列_java 动态规划 最长递增子序列_02


4、接下来需要获得 dp[3] 的值,nums[3] 之前有一个元素 nums[2] 比自己小,因此 dp[3] = dp[2] + 1 = 2,表示到以 nums[3] 为结尾,最长上升子序列长度为 2,即 nums[2] -> nums[3]。

java 动态规划 最长递增子序列 leetcode 最长递增子序列_数组_03


5、接着要获得 dp[4] 的值,nums[4] 之前有一个元素 nums[2] 比自己小,因此 dp[4] = dp[2] + 1 = 2,表示以 nums[4] 为结尾,最长上升子序列长度为 2,即 nums[2] -> nums[4]。

java 动态规划 最长递增子序列 leetcode 最长递增子序列_子序列_04

6、接着要获得 dp[5] 的值,nums[5] 之前有元素 nums[2]、nums[3]、nums[4] 比自己小,其中,dp[3] 的数值是最大的,因此,dp[5] = dp[3] + 1 = 3,表示以 nums[5] 为结尾,最长上升子序列长度为 3,即 nums[2] -> nums[3] -> nums[5]。

java 动态规划 最长递增子序列 leetcode 最长递增子序列_递增子序列_05


7、接下来需要获得 dp[6] 的值,nums[6] 之前的所以元素都比它小,因此在之前的元素中找到 dp[5] 的数值最大,dp[6] = dp[5] + 1 = 4,表示以 nums[6] 结尾,最长上升子序列长度为 4,即 nums[2] -> nums[3] -> nums[5] -> nums[6]。

java 动态规划 最长递增子序列 leetcode 最长递增子序列_数组_06


8、接下来获得 dp[7] 的值,比 nums[7] 小的元素有 nums[0] ~ nums[5],找到其中 dp 数值最大的元素 nums[5],因此 dp[7] = dp[5] + 1 = 4,表示以 nums[7] 为结尾,最长上升子序列长度为 4,即 nums[2] -> nums[3] -> nums[5] -> nums[7]。

java 动态规划 最长递增子序列 leetcode 最长递增子序列_java 动态规划 最长递增子序列_07


虽然找到了全部的 dp 值,那我们能直接以最后一个 dp 值作为结果输出吗,当然不行,因为用上面的例子,dp[last] 表示的是以 18 为结尾最长上升子序列,我们要找的最长上升子序列并不一定以最后一个元素为结尾,因此我们还需要再对 dp 数组做一遍遍历,找到 dp 的最大值。

java 动态规划 最长递增子序列 leetcode 最长递增子序列_数组_08


reference 代码:

def lengthoflist(nums):
    dp=[1 for k in nums]
    for i in range(1,len(nums)):
        maxs=dp[i-1]
        for k in range(i-1,-1,-1):
            if nums[i]>nums[k]:
                maxs=max(dp[k]+1,maxs)
        dp[i]=maxs
    return dp[-1]