当前位置: 首页 > article >正文

笔记:代码随想录算法训练营day43:LeetCode300.最长递增子序列、674. 最长连续递增序、 718. 最长重复子数组

学习资料:代码随想录

300.最长递增子序列

力扣题目链接

感觉挺难,个人一点小感想,还是要回到动态规划的定义,是一种递推的思想,该状态可由上一个状态推导得出。然后这道题的解法有一个关键点在dp[i]的定义为位置i处之前(包括i)的数组包含的最长子序列,而且最长最序列的末尾一定是在位置i,后面两道也一样

看递推公式

for (int i = 1; i < nums.size(); i++) {
            for (int j = 0; j < i; j++) {
                if (nums[i] > nums[j]) dp[i] = max(dp[i], dp[j] + 1);
            }
            if (dp[i] > result) result = dp[i]; // 取长的子序列
        }

i在外层,j在内层,看起来是一遍一遍在遍历0-i,这样等于是把每个子数组都遍历过了,然后不停更新最长的,正是因为 最长最序列的末尾一定是在位置i,所以才要不停更新,而不是直接遍历完成后记录最后一个,也正是因为最长最序列的末尾一定是在位置i,所以要把每一个子序列都检查一遍

初始化:最小也是个1,所以初始化为1,从第二个数开始检查

// 定义:dp[i]表示以第0个数字为开头第i个数字为结尾的子数组包含的最长严格递增子序列(注意这个子序列是一定把第i个数字包括进去的)
// 递推公式:用i去固定子数组的最后一个数字,用j去遍历这个子数组,当数字i比数字j大的时候,要检查dp[j]+1的值和此时dp[i]的值,看是否需要更新dp[i],在之前更新过的情况下是不需要dp[j]+1来更新的
// 初始化:1个数字最长严格递增子序列长度是1,先把整个dp数组初始化为1
// 遍历顺序:顺着,dp[i]是由0到i-1各位置的最长递增子序列推导而来
// 打印:

class Solution {
public:
    int lengthOfLIS(vector<int>& nums) {
        if(nums.size()==1) return 1;
        vector<int> dp(nums.size(),1);
        int result = 0;
        for(int i=1;i<nums.size();i++){
            for(int j=0;j<i;j++){
                if(nums[i]>nums[j]) dp[i]=max(dp[i],dp[j]+1);
            }
            result = max(result,dp[i]);
        }
        return result;
    }
};

674. 最长连续递增序列

力扣题目链接

虽然说都是求递增子序列的题,但是解法和上一道题一比像是两个题一样。因为需要是连续的了,所以直接把整个数组检查一遍就可以了,遇见连续的了再记录就可以了

class Solution {
public:
    int findLengthOfLCIS(vector<int>& nums) {
        vector<int> dp(nums.size(),1);
        int result = 1;
        for(int i=1;i<nums.size();i++){
            if(nums[i]>nums[i-1]) dp[i] = dp[i-1]+1;
            result = max(result,dp[i]);
        }
        return result;
    }
};

贪心:

class Solution {
public:
    int findLengthOfLCIS(vector<int>& nums) {
        int count = 1;
        int result = 1;
        for(int i=1;i<nums.size();i++){
            if(nums[i]>nums[i-1]) count++;
            else count = 1;
            result = max(result,count);
        }
        return result;
    }
};

 

718. 最长重复子数组

力扣题目链接

思路:找两个数组中重复的,要上到二维了。

定义:dp[i][j]表示num1第i-1个数及其之前的数组成的子数组和nums2第j-1个数及其之前的数组成的子数组给公共数组,这样i,j分别要遍历到nums1.size()和nums2.size(),而且最左边一列和最上边一行是只有推导上的意义,不管怎么说,dp二维数组得从0,0开始

为什么是nums1[i-1]==nums2[j-1],因为定义就是这样的,这样写正好是能遍历完的

// 定义:dp[i][j]表示在nums1第i-1个数,nums2第j-1个数之前包含的公共的长度最长子数组的长度
// 递推公式:看两个数组两个位置的前一个状态是否相等,正好dp数组定义就是前一个位置
// 初始化:第一列和第一行相当于是一个虚拟行和列了,实际上数组不是从这两列开始的,根据递推公式,看i,j都是1的情况,第一行和第一列应该是都初始为0,那其实整个dp二维数组都应该初始化为0
// 遍历顺序:i,j都从1开始遍历
// 打印:略

class Solution {
public:
    int findLength(vector<int>& nums1, vector<int>& nums2) {
        vector<vector<int>> dp(nums1.size()+1,vector<int>(nums2.size()+1,0));
        // 因为都初始化为0了,两顶行的初始化可以省略了
        int result = 0;
        for(int i=1;i<=nums1.size();i++){
            for(int j=1;j<=nums2.size();j++){
                if(nums1[i-1]==nums2[j-1]){
                    dp[i][j] = dp[i-1][j-1]+1;
                }
                result = max(result,dp[i][j]);
            }
        }
        return result;
    }
};


http://www.kler.cn/a/584086.html

相关文章:

  • 大模型在老年性白内障诊疗全流程中的应用研究报告
  • Android wgs84坐标系转CGCS2000坐标系
  • CentOS8+Zabbix7.2.4解决中文显示问题
  • rtsp在网页上显示(webrtc-stream)
  • Pytest自动化测试框架pytest-xdist分布式测试插件
  • JAVA面试_进阶部分_Java JVM:垃圾回收(GC 在什么时候,对什么东西,做了什么事情)
  • 【Unity】在项目中使用VisualScripting
  • 计算机视觉算法实战——驾驶员分心检测(主页有源码)
  • 大模型开源的工具包有哪些特殊符号可以使用;SEP 是什么
  • HTML 表格的详细介绍与应用
  • [洛谷]P1123 取数游戏
  • rv1106 PWM控制
  • javaWeb的详细笔记(超详细版本)
  • AI大数据挖掘的威力
  • 【鸿蒙开发】Hi3861学习笔记- GPIO之按键
  • 小白学习:提示工程(什么是prompt)
  • PostgreSQL存储管理体系结构学习笔记2
  • Linux第二次练习
  • hive-进阶版-1
  • 嵌入式开发工程师笔试面试指南-模电基础