算法学习——LeetCode力扣动态规划篇8

news2024/11/27 11:10:19

算法学习——LeetCode力扣动态规划篇8

在这里插入图片描述

300. 最长递增子序列

300. 最长递增子序列 - 力扣(LeetCode)

描述

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

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

示例

示例 1:

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

示例 2:

输入:nums = [0,1,0,3,2,3]
输出:4

示例 3:

输入:nums = [7,7,7,7,7,7,7]
输出:1

提示

1 <= nums.length <= 2500
-104 <= nums[i] <= 104

代码解析

动态规划
  • dp[i]的定义
    dp[i]表示i之前包括i的以nums[i]结尾最长上升子序列的长度

  • 状态转移方程
    位置i的最长升序子序列等于j从0到i-1各个位置的最长升序子序列 + 1 的最大值。
    所以:if (nums[i] > nums[j]) dp[i] = max(dp[i], dp[j] + 1);
    注意这里不是要dp[i] 与 dp[j] + 1进行比较,而是我们要取dp[j] + 1的最大值。

  • dp[i]的初始化
    每一个i,对应的dp[i](即最长上升子序列)起始大小至少都是1.

  • 确定遍历顺序
    dp[i] 是有0到i-1各个位置的最长升序子序列 推导而来,那么遍历i一定是从前向后遍历。
    j其实就是0到i-1,遍历i的循环在外层,遍历j则在内层

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=0 ; 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];
        }
        return result;
    }
};

674. 最长连续递增序列

674. 最长连续递增序列 - 力扣(LeetCode)

描述

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

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

示例

示例 1:

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

示例 2:

输入:nums = [2,2,2,2,2]
输出:1
解释:最长连续递增序列是 [2], 长度为1。

提示

1 <= nums.length <= 104
-109 <= nums[i] <= 109

代码解析

动态规划
  • dp数组定义
    i点前连续递增序列的个数
  • dp的迭代
    if(nums[i] > nums[i-1]) dp[i] = dp[i-1] + 1;
    当i的值大于i-1,dp[i] = dp[i-1] + 1
  • dp初始化
    全都设置为1
    自己认为是一个元素的递增数组
class Solution {
public:
    int findLengthOfLCIS(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++)
        {
            if(nums[i] > nums[i-1]) dp[i] = dp[i-1] + 1;
            if(dp[i]>result) result = dp[i];
        }

        return result;
    }
};

718. 最长重复子数组

718. 最长重复子数组 - 力扣(LeetCode)

描述

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

示例

示例 1:

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

示例 2:

输入:nums1 = [0,0,0,0,0], nums2 = [0,0,0,0,0]
输出:5

提示

1 <= nums1.length, nums2.length <= 1000
0 <= nums1[i], nums2[i] <= 100

代码解析

动态规划
  • 确定dp数组含义
    dp[i][j] :以下标i - 1为结尾的A(A的第i个元素),和以下标j - 1为结尾的B(B的第j个元素),最长重复子数组长度为dp[i][j]。
  • 确定递推公式
    根据dp[i][j]的定义,dp[i][j]的状态只能由dp[i - 1][j - 1]推导出来。
    即当A[i - 1] 和B[j - 1]相等的时候,dp[i][j] = dp[i - 1][j - 1] + 1;
  • 初始化
    dp[0][0]、dp[i][0]、dp[0][j]都为0,因为下标为0意味着没有元素进行匹配,因此匹配的个数也是0。从dp[i][j]开始有意义,即nums1和nums2都拿出了一个元素
class Solution {
public:
    int findLength(vector<int>& nums1, vector<int>& nums2) {
    	//dp数组下标i和j意味着第几个元素,因此长度+1
       vector<vector<int>>  dp(nums1.size()+1 , vector<int>(nums2.size()+1,0));
        int result = 0 ;
        for(int i=0 ; i<nums1.size() ;i++)
        {
            for(int j=0 ;j<nums2.size();j++)
            {
                if(nums1[i] == nums2[j])
                    dp[i+1][j+1] = dp[i][j]+1;
                if(dp[i+1][j+1] > result) result = dp[i+1][j+1];
            }
        
        }
         
        // for(int i=0 ; i<=nums1.size() ;i++)
        // {
        //     for(int j=0 ;j<=nums2.size();j++)
        //     {
        //         if(dp[i][j] > result) result = dp[i][j];
        //          cout<<dp[i][j]<<' ';
        //     }
        //      cout<<endl;
        // }
         return result;
    }
};

1143. 最长公共子序列

1143. 最长公共子序列 - 力扣(LeetCode)

描述

给定两个字符串 text1 和 text2,返回这两个字符串的最长 公共子序列 的长度。如果不存在 公共子序列 ,返回 0 。

一个字符串的 子序列 是指这样一个新的字符串:它是由原字符串在不改变字符的相对顺序的情况下删除某些字符(也可以不删除任何字符)后组成的新字符串。

例如,“ace” 是 “abcde” 的子序列,但 “aec” 不是 “abcde” 的子序列。
两个字符串的 公共子序列 是这两个字符串所共同拥有的子序列。

示例

示例 1:

输入:text1 = “abcde”, text2 = “ace”
输出:3
解释:最长公共子序列是 “ace” ,它的长度为 3 。

示例 2:

输入:text1 = “abc”, text2 = “abc”
输出:3
解释:最长公共子序列是 “abc” ,它的长度为 3 。

示例 3:

输入:text1 = “abc”, text2 = “def”
输出:0
解释:两个字符串没有公共子序列,返回 0 。

提示

1 <= text1.length, text2.length <= 1000
text1 和 text2 仅由小写英文字符组成。

代码解析

  • dp数组含义
    dp[i][j]:长度为[0, i - 1]的字符串text1与长度为[0, j - 1]的字符串text2的最长公共子序列为dp[i][j](即前i个字符和前j个字符匹配)
  • 递推公式
    • 当text1[i] == text2[j]
      当前匹配的i和j是相同的字符,dp[i+1][j+1] = dp[i][j] + 1;
      dp应该是不包括第i+1 和第j+1字符之前匹配成功个数+1
      要把i+1和j+1让出来。
    • 当text1[i] != text2[j]
      当前匹配的i和j是不同的字符,dp[i+1][j+1] = max(dp[i+1][j],dp[i][j+1]);
      dp为包括i+1字符或者包括j+1字符的最大值
    • 当匹配成功时
      为什么不是 dp[i+1][j+1] = max(dp[i+1][j],dp[i][j+1])+1;
      因为会造成一个字母匹配多次
      例如 text1中有一个b,text2中有两个b
      在i+1为text1的b,j+1为text2中第二个b时:
      max(dp[i+1][j],dp[i][j+1])包含和text2中第一个b匹配,+1是和第二个b匹配。
      则造成了text1中字母b与text2中两个b分别匹配。
      因此应该是dp[i+1][j+1] = dp[i][j] + 1,这样让开要匹配的字符
class Solution {
public:
    int longestCommonSubsequence(string text1, string text2) {
        vector<vector<int>> dp(text1.size()+1 , vector<int>(text2.size()+1 ,0) );

        for(int i=0 ;i<text1.size();i++)
        {
            for(int j=0; j<text2.size();j++)
            {
                
                if(text1[i] == text2[j])
                    dp[i+1][j+1] = dp[i][j] + 1; 
                else
                    dp[i+1][j+1] = max(dp[i+1][j],dp[i][j+1]);
                   
            }
        }
        //  for(int i=0 ;i<=text1.size();i++)
        // {
        //     for(int j=0; j<=text2.size();j++)
        //     {
        //         cout<<dp[i][j]<<' ';
        //     }
        //     cout<<endl;
        // }
        return dp[text1.size()][text2.size()];
    }
};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1556833.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

会话跟踪技术(Session 以及Cookie)

一: 前提概要 1>会话: 会话指的是用户打开浏览器, 访问某些web服务器资源的时候, 会话就会进行建立, 直到有一方断开, 那么会话才会结束, 需要注意的一点是, 一次的会话可以有多次的请求以及响应 2>会话跟踪: 是一种用于维护浏览器状态的方法, 服务器需要识别多次的请求,…

基于springboot的船舶维保管理系统

文章目录 项目介绍主要功能截图&#xff1a;部分代码展示设计总结项目获取方式 &#x1f345; 作者主页&#xff1a;超级无敌暴龙战士塔塔开 &#x1f345; 简介&#xff1a;Java领域优质创作者&#x1f3c6;、 简历模板、学习资料、面试题库【关注我&#xff0c;都给你】 &…

深入理解Docker-使用Docker有什么优势?

Docker是什么&#xff1f; 我们先给出Docker官网给出的定义来看下Docker是什么&#xff1f; Docker加速你应用的构建&#xff0c;共享和运行。 怎么来加速的那&#xff1f; without tedious envionment configuration or management 不用进行哪些乏味的环境配置和管理。 怎么…

U盘无法打开?教你几招轻松解决数据恢复难题

在日常生活和工作中&#xff0c;U盘作为移动存储设备&#xff0c;承载着我们大量的重要数据。然而&#xff0c;当某一天我们满怀期待地将U盘插入电脑&#xff0c;却发现它无法被正常打开时&#xff0c;那种焦虑和挫败感简直让人崩溃。我们可能会尝试各种方法&#xff0c;如重新…

java将文件转成流文件返回给前端

环境&#xff1a;jdk1.8&#xff0c;springboot2.5.3,项目端口号&#xff1a;9100 1.待转换的文件 一、路径 二、文件内容 2.controller中代码 package com.example.pdf.controller;import com.example.pdf.service.GetFileStreamService; import org.springframework.web.b…

Java项目修改了代码总是不生效咋么个事

1.问题发现 自己修改了yml配置文件&#xff0c;然后发现重启项目访问还是原来的配置 查看target下的class文件 发现&#xff0c;这个值并没有变&#xff0c;也就是我们修改完代码其实是没有触发编译文件重新生成class的&#xff0c;这时候我们可以手动解决&#xff0c;选择m…

外包干了5天,技术退步明显.......

先说一下自己的情况&#xff0c;大专生&#xff0c;18年通过校招进入杭州某软件公司&#xff0c;干了接近4年的功能测试&#xff0c;今年年初&#xff0c;感觉自己不能够在这样下去了&#xff0c;长时间呆在一个舒适的环境会让一个人堕落! 而我已经在一个企业干了四年的功能测…

【Web】NSSCTF Round#20 Basic 个人wp

目录 前言 真亦假&#xff0c;假亦真 CSDN_To_PDF V1.2 前言 感谢17&#x1f474;没让我爆零 真亦假&#xff0c;假亦真 直接getshell不行&#xff0c;那就一波信息搜集呗&#xff0c;先开dirsearch扫一下 扫的过程中先试试常规的robots.txt,www.zip,shell.phps,.git,.sv…

笔迹/签名数据集汇总

这里只收集公开/易申请的数据集 数据集发表年份语言最小单元Writers/人规模颜色最小单元文件格式示例图片备注CSAFE Handwriting Database2019英语页9090 人*(3 次*9 个样本) 2430 页300 dpi 扫描png-HWDB2.0-2.22011汉字页1,019每人 5 页,共 5091 页灰度图dgrl-CEDAR2006英语…

【Java面试题】Redis中篇(高可用:主从复制、哨兵、集群)

文章目录 高可用14.Redis如何保证高可用&#xff1f;15.Redis的主从复制&#xff1f;16.Redis主从有几种常见的拓扑结构&#xff1f;17.Redis的主从复制原理了解吗&#xff1f;18.说说主从数据同步的方式&#xff1f;19.主从复制存在的问题&#xff1f;20.Redis Sentinel(哨兵)…

ATFX汇市:欧元区的2月M1增速为-7.7%,潜在通胀下修,欧元币值受冲击

ATFX汇市&#xff1a;衡量经济体的潜在通胀指标&#xff0c;除了CPI数据、失业率数据外&#xff0c;还有M1、M3数据。昨日&#xff0c;欧洲央行公布了2月份欧元区货币发展报告&#xff0c;其中提到&#xff1a;广义货币总量M3的年增长率从1月份的0.1%上升到2024年2月的0.4%&…

多线程JUC 第2季 synchornized和Lock锁(重入,公平)

一 锁 1.1 锁的介绍 synchronized&#xff0c;和lock锁都是一种悲观锁。悲观锁适用于写多场景&#xff0c;乐观锁适用于读多场景&#xff0c;实现策略有&#xff1a;版本号和cas自旋算法。

ubuntu22.04@Jetson Orin Nano安装配置VNC服务端

ubuntu22.04Jetson Orin Nano安装&配置VNC服务端 1. 源由2. 环境3. VNC安装Step 1: update and install xserver-xorg-video-dummyStep 2: Create config for dummy virtual displayStep3: Add the following contents in xorg.conf.dummyStep 4: Update /etc/X11/xorg.con…

CQ 社区版2.10.0 | 新增 SQL 审核、全新英文版上线…

三月中旬&#xff0c;我们预告了 CloudQuery 社区版即将上线的「SQL 审核」功能。现在&#xff0c;它来了&#xff01; 本次社区版 v2.10.0&#xff0c;除了 SQL 审核功能&#xff0c;我们还在手动授权、连接分组等模块做了新功能和优化。 新增功能 新增 SQL 审核功能 支持…

【STM32嵌入式系统设计与开发】——13WWDG(窗口看门狗应用)

这里写目录标题 一、任务描述二、任务实施1、WWDG工程文件夹创建2、函数编辑&#xff08;1&#xff09;主函数编辑&#xff08;2&#xff09;USART1初始化函数(usart1_init())&#xff08;3&#xff09;USART数据发送函数&#xff08; USART1_Send_Data&#xff08;&#xff09…

访学博后须知|携带手机等电子产品入境美国注意事项

美国对携带手机等电子产品入境有着严格的规定&#xff0c;因此知识人网小编提醒拟出国做访问学者、博士后或联合培养的博士生了解以下注意事项&#xff0c;尽量减少不必要的麻烦。 随着互联网的普及&#xff0c;手机等电子产品在人民生活中占有不可或缺的地位。因为研究和工作需…

LInux: fork()究竟是如何工作的?为何一个变量能够接受两个返回值?

LInux: fork函数究竟是如何工作的&#xff1f;为何一个变量能够接受两个返回值&#xff1f; 前言一、fork()用法二 、fork()应用实例展示三、fork()工作原理3.1 为什么要创建子进程&#xff1f;3.2 fork()究竟干了些什么&#xff1f;3.3 fork为什么会存在两个返回值&#xff1f…

opengl草稿复习,承上启下(一)

目录 1、链接文件夹中的cpp 2、链接资源到输出目录 3、多编译目标 4、cmakelist添加库 4、添加glfw和glad 5、glfw运行 6、NDC、VBO、VAO 7、渐变三角形 8、渲染两个三角形 9、渲染两个三角形&#xff0c;同时基于原来颜色进行渐变 10、三角形渲染模块化 11、纹理渲…

深度学习中的模型蒸馏技术:实现流程、作用及实践案例

在深度学习领域&#xff0c;模型压缩与部署是一项重要的研究课题&#xff0c;而模型蒸馏便是其中一种有效的方法。 模型蒸馏&#xff08;Model Distillation&#xff09;最初由Hinton等人在2015年提出&#xff0c;其核心思想是通过知识迁移的方式&#xff0c;将一个复杂的大模型…

适合新手小白的wordpress详细安装教程

1、下载程序 到wordpress官方网站下载wordpress程序&#xff0c;官方下载地址&#xff1a;Download | WordPress.org China 简体中文。 下载最新版的wordpress程序 https://cn.wordpress.org/latest-zh_CN.zip 2、上传程序 上传程序前先确认主机是否符合安装的环境要求&…