300.最长递增子序列
思路:动态规划五步曲:
- dp[i]表示从0到i,以nums[i]结尾的最长递增子序列的长度。
- 从0到i遍历j,递推公式:if(nums[i]>nums[j]) dp[i] = max(dp[i], dp[j] + 1)
- 因为每一个数的子序列大小为1,所以dp[i]都初始化为1
- 从递推公式可以看出需要从前向后遍历。
- 举例说明
class Solution {
public int lengthOfLIS(int[] nums) {
// dp[i] 表示从0到i,以nums[i]结尾的递增子序列长度
int res = 1;
int[] dp = new int[nums.length];
for (int i = 0; i < dp.length; i++) {
dp[i] = 1;
}
for (int i = 1; i < dp.length; i++) {
for (int j = 0; j < i; j++) {
if (nums[i] > nums[j]) {
dp[i] = Math.max(dp[i], dp[j] + 1);
if (dp[i] > res) res = dp[i];
}
}
}
return res;
}
}
674. 最长连续递增序列
思路:本题相对于上一题来说多了一个连续的条件,动态规划五步曲:
- dp[i] 表示0-i以nums[i]为结尾的连续递增子序列长度
- 递推公式,if(nums[i] > nums[i - 1]) dp[i] = max(dp[i], dp[i - 1]+1)
- 初始化所有的dp[i] = 1;
- 从前向后遍历
- 举例说明
class Solution {
public int findLengthOfLCIS(int[] nums) {
// dp[i] 表示0-i以nums[i]为结尾的连续递增子序列长度
int[] dp = new int[nums.length];
int res = 1;
for (int i = 0; i < dp.length; i++) {
dp[i] = 1;
}
for (int i = 1; i < dp.length; i++) {
if (nums[i] > nums[i - 1]) {
dp[i] = Math.max(dp[i], dp[i - 1] + 1);
}
if (res < dp[i]) {
res = dp[i];
}
}
return res;
}
}
718. 最长重复子数组
思路:动态规划五步曲:
- dp[i][j] 表示nums1从0到i,和nums2从0到j最长重复子数组长度。
- 递推公式:if(nums1[i] == nums2[j]) dp[i][j] = dp[i - 1][j - 1] + 1
- 初始化第一行和第一列,如果相同就初始化为1,如果不同就初始化为0.
- 遍历顺序,需要从前向后遍历,先遍历i或者j都可以。
- 举例说明
class Solution {
public int findLength(int[] nums1, int[] nums2) {
// dp[i][j] 表示nums1从0到i,和nums2从0到j最长重复子数组长度。
int[][] dp = new int[nums1.length][nums2.length];
int res = 0;
for (int i = 0; i < nums1.length; i++) {
if (nums1[i] == nums2[0]) {
dp[i][0] = 1;
res = 1;
}
}
for (int j = 0; j < nums2.length; j++) {
if (nums2[j] == nums1[0]) {
dp[0][j] = 1;
res = 1;
}
}
for (int i = 1; i < nums1.length; i++) {
for (int j = 1; j < nums2.length; j++) {
if (nums1[i] == nums2[j]) {
dp[i][j] = dp[i - 1][j - 1] + 1;
if (res < dp[i][j]) res = dp[i][j];
}
}
}
return res;
}
}