300. Longest Increasing Subsequence
题目链接:300. Longest Increasing Subsequence
思路链接:代码随想录动态规划-最长递增子序列
思路
- 定义dp数组:到第i个元素时,最长的子序列长度为dp[i]
- 递推公式:
// nums[j]为nums[i]之前的元素
if (nums[i] > nums[j]) {
dp[i] = Math.max(dp[i - 1], dp[j] + 1);
}
- 数组初始化:都为1,因为最小长度为1
- 遍历顺序
- 打印数组
Code
class Solution {
public int lengthOfLIS(int[] nums) {
// 1. 定义dp数组
// 到第i个元素时,最长的子序列长度为dp[i]
int[] dp = new int[nums.length];
// 2. 递推公式
// nums[j]为nums[i]之前的元素
// if (nums[i] > nums[j]) {
// dp[i] = Math.max(dp[i - 1], dp[j] + 1);
// }
// 3. 数组初始化
for (int i = 0; i < nums.length; i++) {
dp[i] = 1;
}
// 4. 遍历顺序
int result = 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); // 让dp[i]达到当前所能到达的最大值
}
if (result < dp[i]) result = dp[i]; // 更新result
}
// 5. 打印数组
// for (int item : dp) {
// System.out.print(item + " ");
// }
// System.out.println("");
}
return result;
}
}
674. Longest Continuous Increasing Subsequence
题目链接:674. Longest Continuous Increasing Subsequence
思路链接:代码随想录动态规划-最长连续递增序列
思路
这题与上一题不同的地方在于递推公式,这题是连续的子序列,因此不需要遍历i元素之前的元素了
// 2. 递推公式
if (nums[i] > nums[i - 1]) {
dp[i] = Math.max(dp[i], dp[i - 1] + 1); OR dp[i] = dp[i - 1] + 1;
}
Code
class Solution {
public int findLengthOfLCIS(int[] nums) {
// 1. 确定dp数组
// 到第i个元素时连续子序列的最大长度为dp[i]
int[] dp = new int[nums.length];
// 2. 递推公式
// if (nums[i] > nums[i - 1]) {
// dp[i] = Math.max(dp[i], dp[i - 1] + 1); OR dp[i] = dp[i - 1] + 1;
// }
// 3. 初始化数组
Arrays.fill(dp, 1);
int result = 1;
// 4. 遍历顺序
for (int i = 1; i < nums.length; i++) {
if (nums[i] > nums[i - 1]) {
// dp[i] = Math.max(dp[i], dp[i - 1] + 1); 没必要
dp[i] = dp[i - 1] + 1;
}
if (result < dp[i]) result = dp[i];
// 5.打印数组
// for (int item : dp) {
// System.out.print(item + " ");
// }
// System.out.println("");
}
return result;
}
}
718. Maximum Length of Repeated Subarray
题目链接:718. Maximum Length of Repeated Subarray
思路链接:代码随想录动态规划-最长重复子数组
思路
这道题需要注意确定dp二维数组:结尾下标为i - 1的数组A与结尾下标为j - 1的数组B,最大长度为dp[i][j],注意因为nums1[0]与nums2[0]不相同,所以要dp行列size都要+1.
递推公式就是如果前一个元素相同,那么本元素的dp[i][j]要在前一个元素的基础上加上1
初始化数组都要为0,因为根据dp[i][j]的定义,dp[i][0] 和dp[0][j]其实都是没有意义的!但dp[i][0] 和dp[0][j]要初始值,因为 为了方便递归公式dp[i][j] = dp[i - 1][j - 1] + 1;
遍历顺序先遍历i还是先遍历j两者都可以
Code
class Solution {
public int findLength(int[] nums1, int[] nums2) {
// 1. 确定dp数组
// 结尾下标为i - 1的数组A与结尾下标为j - 1的数组B,最大长度为dp[i][j]
int[][] dp = new int[nums1.length + 1][nums2.length + 1]; // 因为nums1[0]与nums2[0]不相同,所以要+1
// 2. 递推公式
// if (nums[i - 1] == nums[j - 1]) {
// dp[i][j] = dp[i - 1][j - 1] + 1;
// }
// 3. 初始化数组 都为0
// for (int i = 0; i < nums1.length; i++) {
// for (int j = 0; j < nums2.length; j++) {
// dp[i][j] = 0;
// }
// }
int result = 0;
// 4. 遍历顺序
for (int i = 1; i < dp.length; i++) {
for (int j = 1; j < dp[0].length; j++) {
if (nums1[i - 1] == nums2[j - 1]) {
dp[i][j] = dp[i - 1][j - 1] + 1;
}
if (result < dp[i][j]) result = dp[i][j];
}
// 5. 打印数组
// for (int[] row : dp) {
// for (int item : row) {
// System.out.print(item + " ");
// }
// System.out.println();
// }
// System.out.println();
}
return result;
}
}