Leetcode 300.最长递增子序列

题目要求

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

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

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

示例2:
输入:nums = [0,1,0,3,2,3]
输出:4

示例3:
输入:nums = [7,7,7,7,7,7,7]
输出:1

动态规划

动规五部曲

  1. 确定dp数组(dp table)以及下标的含义
    dp[i]:以nums[i]结尾的最长递增子序列的长度

  2. 确定递推公式

    • 对于每个nums[i],都要和它前面的所有元素numsj进行比较
    • 如果nums[i]>nums[j],说明可以接在nums[j]后面形成递增子序列,所以此时以nums[i]结尾的最长递增子序列的长度可以由以nums[j]结尾的最长递增子序列的长度+1得到,即dp[i] = dp[j] + 1
    • 但是j有多个,所以要取所有满足条件的dp[j]+1中的最大值,即
      dp[i] = Math.max(dp[i], dp[j] + 1) (0<=j<i && nums[i]>nums[j])
    • 如果没有任何一个nums[j]<nums[i],说明以nums[i]结尾的最长递增子序列只能是它自己,所以dp[i]=1
  3. dp数组如何初始化
    dp数组每个元素初始化为1,因为每个元素单独成一个子序列,长度至少为1

  4. 确定遍历顺序
    从前往后遍历。

  5. 举例推导dp数组

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Solution {
public int lengthOfLIS(int[] nums) {
int[] dp = new int[nums.length];
for (int i = 0; i < nums.length; i++) {
dp[i] = 1;
}
int res = 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(dp[i],res);
}

return res;
}
}