刷题第52天 | 300.最长递增子序列、674. 最长连续递增序列、718. 最长重复子数组

300. Longest Increasing Subsequence

题目链接:300. Longest Increasing Subsequence
思路链接:代码随想录动态规划-最长递增子序列

思路

  1. 定义dp数组:到第i个元素时,最长的子序列长度为dp[i]
  2. 递推公式:
// nums[j]为nums[i]之前的元素
if (nums[i] > nums[j]) {
	dp[i] = Math.max(dp[i - 1], dp[j] + 1)}
  1. 数组初始化:都为1,因为最小长度为1
  2. 遍历顺序
  3. 打印数组

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;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值