• 代码随想录Day_52打卡


    ①、最长递增子序列

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

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

    事例:

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

    思路:

           使用动态规划,dp含义:dp[i]表示数组nums到下标为i时的最长递增子序列,由于涉及到删除数字,故每个数字都应该往前面比较,故在赋值时,应取dp[i]和dp[j] + 1的最大值。

    动态规划:

            dp定义及含义:dp[i]表示到nums[i]时的最长递增子序列

            状态转移方程:if(nums[i] == nums[j])   dp[i] = Math.max(dp[i],dp[j] + 1) j为0到i - 1

           初始化:全部填充为1 因为不包括空集

            遍历顺序:外层遍历数组,内层遍历0到i - 1

            dp中的最大值即为答案。

    代码:

    1. public int lengthOfLIS(int[] nums) {
    2. if(nums.length == 1) return 1;
    3. int[] dp = new int[nums.length];
    4. Arrays.fill(dp,1);
    5. int res = 1;
    6. for(int i = 1;i < nums.length;i++){
    7. for(int j = 0;j < i;j++){
    8. if(nums[i] > nums[j]) dp[i] = Math.max(dp[i],dp[j] + 1);
    9. }
    10. res = Math.max(dp[i],res);
    11. }
    12. return res;
    13. }

    ②、最长连续递增序列

    给定一个未经排序的整数数组,找到最长且 连续递增的子序列,并返回该序列的长度。

    连续递增的子序列 可以由两个下标 l 和 rl < r)确定,如果对于每个 l <= i < r,都有 nums[i] < nums[i + 1] ,那么子序列 [nums[l], nums[l + 1], ..., nums[r - 1], nums[r]] 就是连续递增子序列。

    事例:

    输入:nums = [1,3,5,4,7]
    输出:3
    解释:最长连续递增序列是 [1,3,5], 长度为3。
    尽管 [1,3,5,7] 也是升序的子序列, 但它不是连续的,因为 5 和 7 在原数组里被 4 隔开。

    思路:

            跟上一题类似,只是要求连续,使用动态规划的话,只需要在改动下状态转移方程。上一题中,内层套用for循环遍历取得最大值,本质就是跳过其中的一些数达到删除效果,这题要求连续,则删除for循环,只需与前一个数比较即可。

    动态规划:

            dp定义及含义:dp[i]表示到nums[i]时的最长连续递增序列

            状态转移方程:if(dp[i] == dp[i - 1]) dp[i] = dp[i - 1] + 1

           初始化:全部填充为1 因为不包括空集

            遍历顺序:从左到右遍历数组nums

            dp中的最大值即为答案。

    代码:

    1. public int findLengthOfLCIS(int[] nums) {
    2. //动态规划
    3. // if(nums.length == 1) return 1;
    4. // int[] dp = new int[nums.length];
    5. // Arrays.fill(dp,1);
    6. // int res = 1;
    7. // for(int i = 1;i < nums.length;i++){
    8. // if(nums[i] > nums[i - 1]) dp[i] = dp[i - 1] + 1;
    9. // res = Math.max(res,dp[i]);
    10. // }
    11. // return res;
    12. int res = 1;
    13. int count = 1;
    14. for(int i = 1;i < nums.length;i++){
    15. if(nums[i] > nums[i - 1]) count++;
    16. else{
    17. res = Math.max(res,count);
    18. count = 1;
    19. }
    20. }
    21. res = Math.max(res,count);
    22. return res;
    23. }

    ③、最长重复子数组

    给两个整数数组 nums1 和 nums2 ,返回 两个数组中 公共的 、长度最长的子数组的长度 

    事例:

    输入:nums1 = [1,2,3,2,1], nums2 = [3,2,1,4,7]
    输出:3
    解释:长度最长的公共子数组是 [3,2,1] 。

    思路:

            这题涉及到匹配过程,由于有两个数组,长度可能不同,则dp需要两个维度记录。创建dp数组,其中dp[i][j]表示nums1从0到i - 1与nums2从0到j - 1的最长重复子数组,其中dp[i][j]只能从dp[i - 1][j - 1]推导,且第一行和第一列没实际意义,初始化为0。

    动态规划:

            dp定义及含义:dp[i][j]表示nums1从0到i - 1与nums2从0到j - 1的最长重复子数组

            状态转移方程:if(nums1[i - 1] == nums2[j - 1]) dp[i][j] = dp[i - 1][j - 1] + 1

            初始化:第一行和第一列初始化为0

            遍历顺序:嵌套遍历两个nums数组,其中要注意i、j与数组的对应关系

            dp中的最大值即为答案。

    代码:

    1. public int findLength(int[] nums1, int[] nums2) {
    2. //二维数组
    3. int[][] dp = new int[nums1.length + 1][nums2.length + 1];
    4. int res = 0;
    5. for(int i = 1;i < nums1.length + 1;i++){
    6. for(int j = 1;j < nums2.length + 1;j++){
    7. if(nums1[i - 1] == nums2[j - 1]) dp[i][j] = dp[i - 1][j - 1] + 1;
    8. res = Math.max(res,dp[i][j]);
    9. }
    10. }
    11. return res;
    12. }

    与背包问题类似:也可以转化为一维数组,此时dp[j]表示nums2从0到j与nums1的最长重复子数组,由前面的二维数组dp可看出,dp的赋值依赖于前一行或前一列的结果,故从上到下将值覆盖可以将dp简化为一维数组。套用两层for循环,如果匹配,dp[j] = dp[j - 1] + 1,不匹配则赋为0.

    动态规划:

            

    dp定义及含义:dp[j]表示nums2从0到j - 1与nums1的最长重复子数组

            状态转移方程:if(nums1[i - 1] == nums2[j - 1]) dp[j] = dp[j - 1] + 1

            初始化:全部初始化为0

            遍历顺序:嵌套遍历两个nums数组,先遍历nums1(作为行),再从大到小遍历nums2,避免重复比较。

            dp中的最大值即为答案。

    代码:

    1. public int findLength(int[] nums1, int[] nums2) {
    2. //二维数组
    3. // int[][] dp = new int[nums1.length + 1][nums2.length + 1];
    4. // int res = 0;
    5. // for(int i = 1;i < nums1.length + 1;i++){
    6. // for(int j = 1;j < nums2.length + 1;j++){
    7. // if(nums1[i - 1] == nums2[j - 1]) dp[i][j] = dp[i - 1][j - 1] + 1;
    8. // res = Math.max(res,dp[i][j]);
    9. // }
    10. // }
    11. // return res;
    12. //一维数组
    13. int[] dp = new int[nums2.length + 1];
    14. int res = 0;
    15. for(int i = 1;i < nums1.length + 1;i++){
    16. for(int j = nums2.length;j > 0;j--){
    17. if(nums1[i - 1] == nums2[j - 1]) dp[j] = dp[j - 1] + 1;
    18. else dp[j] = 0;
    19. res = Math.max(res,dp[j]);
    20. }
    21. }
    22. return res;
    23. }

    参考:代码随想录 (programmercarl.com)

  • 相关阅读:
    日志开源组件(六)Adaptive Sampling 自适应采样
    全栈性能测试教程之性能测试相关知识(二) Jmeter的应用
    java线上鲜花销售系统计算机毕业设计源码
    Jackson 工具类
    【快应用】实现自定义导航栏组件
    【Kafka】基本概念
    AD9371 官方例程 NO-OS 主函数 headless 梳理(二)
    Laravel 下实现 Google 2fa 验证
    java网络游戏后台管理系统计算机毕业设计MyBatis+系统+LW文档+源码+调试部署
    如何伪造http头,让后端认为是本地访问
  • 原文地址:https://blog.csdn.net/kk_try_hard/article/details/132651252