dp 数组含义定义一维数组 dp:
注意这里的关键是“以 nums[i] 结尾”。
因为子序列不要求连续,所以不能只看相邻元素,而是要看 i 前面的所有位置 j。只要满足:
就说明 nums[i] 可以接在以 nums[j] 结尾的递增子序列后面。
题目要求整个数组中的最长递增子序列长度,所以最终答案是:
对于位置 i,需要枚举它前面的每一个位置 j:
如果:
说明 nums[i] 可以接在 nums[j] 后面,形成一个更长的递增子序列:
但是满足条件的 j 可能有很多个,我们要选择其中最长的那个,所以状态转移方程是:
一句话总结:以 nums[i] 结尾的最长递增子序列,可以由前面某个比它小的 nums[j] 接上 nums[i] 得到。
dp 数组如何初始化每个位置本身都可以单独组成一个长度为 1 的递增子序列。
所以所有 dp[i] 都初始化为 1:
例如 nums = [10, 9, 2],即使没有任何两个数字能组成递增关系,每个数字自己也至少是一个长度为 1 的递增子序列。
如果 nums 是空数组,直接返回 0。
dp[i] 依赖的是它前面位置的状态 dp[j],其中:
所以外层循环 i 必须从前往后遍历。
对于每个 i,内层循环枚举 0 到 i - 1 的所有位置 j:
这样在计算 dp[i] 时,所有可能用到的 dp[j] 都已经计算完成。
dp 数组以 nums = [10, 9, 2, 5, 3, 7] 为例。
初始化:
| 下标 | 0 | 1 | 2 | 3 | 4 | 5 |
|---|---|---|---|---|---|---|
| nums | 10 | 9 | 2 | 5 | 3 | 7 |
| dp | 1 | 1 | 1 | 1 | 1 | 1 |
从左到右遍历:
i = 0,nums[i] = 10前面没有元素,dp[0] 保持为 1。
i = 1,nums[i] = 9前面只有 10,但 10 < 9 不成立,不能接在后面。
i = 2,nums[i] = 2前面的 10、9 都比 2 大,不能接在后面。
i = 3,nums[i] = 52 < 5,所以 5 可以接在 2 后面:
i = 4,nums[i] = 32 < 3,所以 3 可以接在 2 后面:
i = 5,nums[i] = 72 < 7,可以得到长度 2。
5 < 7,可以得到:
3 < 7,也可以得到:
所以:
最终:
最长递增子序列长度是:
对应的递增子序列可以是:
也可以是:
O(n^2),每个位置 i 都要枚举它前面的所有位置 j。O(n),需要一个长度为 n 的 dp 数组。