动态规划
动态规划思路:
- dp[i]的定义
dp[i]表示i之前包括i的以nums[i]结尾的最长递增子序列的长度
为什么一定表示 “以nums[i]结尾的最长递增子序” ?
因为我们在做递增比较的时候,如果比较 nums[j] 和 nums[i]的大小,那么两个递增子序列一定分别以nums[j]为结尾 和 nums[i]为结尾,要不然这个比较就没有意义了,不是尾部元素的比较那么如何算递增呢。
-
状态转移方程
位置i的最长升序子序列等于j从0到i-1各个位置的最长升序子序列 + 1 的最大值。
if (nums[i] > nums[j]) dp[i] = max(dp[i], dp[j] + 1);
注意这里不是要dp[i] 与 dp[j] + 1进行比较,而是我们要取dp[j] + 1的最大值。 -
dp[i]的初始化
每一个i,对应的dp[i](即最长递增子序列)起始大小至少都是1. -
确定遍历顺序
-
dp[i] 是有0到i-1各个位置的最长递增子序列推导而来
,那么遍历i一定是从前向后遍历。 -
j其实就是遍历0到i-1
,那么是从前到后,还是从后到前遍历都无所谓,只要把 0 到 i-1 的元素都遍历了就行了。
-
class Solution {
public int lengthOfLIS(int[] nums) {
if (nums.length <= 1) return nums.length;
int[] dp = new int[nums.length];
int res = 1;
Arrays.fill(dp, 1);
for (int i = 1; i < nums.length; i++) {
for (int j = 0; j < i; j++) {
if (nums[i] > nums[j]) {
dp[i] = Math.max(dp[i], dp[j] + 1);
}
}
res = Math.max(res, dp[i]);
}
return res;
}
}