代码随想录算法训练营第五十三天丨 动态规划part14

news2024/11/26 11:44:20

1143.最长公共子序列

思路

本题和动态规划:718. 最长重复子数组 (opens new window)区别在于这里不要求是连续的了,但要有相对顺序,即:"ace" 是 "abcde" 的子序列,但 "aec" 不是 "abcde" 的子序列。

继续动规五部曲分析如下:

  • 确定dp数组(dp table)以及下标的含义

dp[i][j]:长度为[0, i - 1]的字符串text1与长度为[0, j - 1]的字符串text2的最长公共子序列为dp[i][j]

有同学会问:为什么要定义长度为[0, i - 1]的字符串text1,定义为长度为[0, i]的字符串text1不香么?

这样定义是为了后面代码实现方便,如果非要定义为长度为[0, i]的字符串text1也可以,卡哥在 动态规划:718. 最长重复子数组 (opens new window)中的「拓展」里 详细讲解了区别所在,其实就是简化了dp数组第一行和第一列的初始化逻辑。

  • 确定递推公式

主要就是两大情况: text1[i - 1] 与 text2[j - 1]相同,text1[i - 1] 与 text2[j - 1]不相同

如果text1[i - 1] 与 text2[j - 1]相同,那么找到了一个公共元素,所以dp[i][j] = dp[i - 1][j - 1] + 1;

如果text1[i - 1] 与 text2[j - 1]不相同,那就看看text1[0, i - 2]与text2[0, j - 1]的最长公共子序列 和 text1[0, i - 1]与text2[0, j - 2]的最长公共子序列,取最大的。

即:dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);

代码如下:

if (text1.charAt(i-1) == text2.charAt(j-1)){
    dp[i][j] = dp[i-1][j-1]+1;
}else{
    dp[i][j] =Math.max(dp[i][j-1],dp[i-1][j]);
}
  • dp数组如何初始化

先看看dp[i][0]应该是多少呢?

test1[0, i-1]和空串的最长公共子序列自然是0,所以dp[i][0] = 0;

同理dp[0][j]也是0。

其他下标都是随着递推公式逐步覆盖,初始为多少都可以,那么就统一初始为0。

代码:

int[][] dp = new int[text1.length()+1][text2.length()+1];
  • 确定遍历顺序

从递推公式,可以看出,有三个方向可以推出dp[i][j],如图:

1143.最长公共子序列

那么为了在递推的过程中,这三个方向都是经过计算的数值,所以要从前向后,从上到下来遍历这个矩阵。

  • 举例推导dp数组

以输入:text1 = "abcde", text2 = "ace" 为例,dp状态如图:

1143.最长公共子序列1

最后红框dp[text1.size()][text2.size()]为最终结果

以上分析完毕,C++代码如下:

class Solution {
    public int longestCommonSubsequence(String text1, String text2) {
        int[][] dp = new int[text1.length()+1][text2.length()+1];
        //Arrays.fill(dp,1);
        int result = 0;
        for (int i = 1; i <= text1.length(); i++) {
            for (int j = 1; j <= text2.length(); j++) {
                if (text1.charAt(i-1) == text2.charAt(j-1)){
                    dp[i][j] = dp[i-1][j-1]+1;
                }else{
                    dp[i][j] =Math.max(dp[i][j-1],dp[i-1][j]);
                }
                result = Math.max(result,dp[i][j]);
            }
        }
        return result;
    }
}
  • 时间复杂度: O(n * m),其中 n 和 m 分别为 text1 和 text2 的长度
  • 空间复杂度: O(n * m)

1035.不相交的线

思路

相信不少录友看到这道题目都没啥思路,来逐步分析一下。

绘制一些连接两个数字 A[i] 和 B[j] 的直线,只要 A[i] == B[j],且直线不能相交!

直线不能相交,这就是说明在字符串A中 找到一个与字符串B相同的子序列,且这个子序列不能改变相对顺序,只要相对顺序不改变,链接相同数字的直线就不会相交。

拿示例一A = [1,4,2], B = [1,2,4]为例,相交情况如图:

其实也就是说A和B的最长公共子序列是[1,4],长度为2。 这个公共子序列指的是相对顺序不变(即数字4在字符串A中数字1的后面,那么数字4也应该在字符串B数字1的后面)

这么分析完之后,大家可以发现:本题说是求绘制的最大连线数,其实就是求两个字符串的最长公共子序列的长度!

那么本题就和我们刚刚讲过的这道题目动态规划:1143.最长公共子序列 (opens new window)就是一样一样的了。

一样到什么程度呢? 把字符串名字改一下,其他代码都不用改,直接copy过来就行了。

其实本题就是求最长公共子序列的长度,介于我们刚刚讲过动态规划:1143.最长公共子序列 (opens new window),所以本题我就不再做动规五部曲分析了。

如果大家有点遗忘了最长公共子序列,就再看一下这篇:动态规划:1143.最长公共子序列(opens new window)

本题代码如下:

class Solution {
    public int maxUncrossedLines(int[] nums1, int[] nums2) {
        int[][] dp = new int[nums1.length+1][nums2.length+1];
        /**
        本题其实核心含义就是找相同的子序列
         */
        for (int i = 1; i <= nums1.length; i++) {
            for (int j = 1; j <= nums2.length; j++) {
                if (nums1[i-1] == nums2[j-1]){
                    dp[i][j] = dp[i-1][j-1]+1;
                }else {
                    dp[i][j] = Math.max(dp[i-1][j],dp[i][j-1]);
                }
            }
        }
        return dp[nums1.length][nums2.length];
    }
}
  • 时间复杂度: O(n * m)
  • 空间复杂度: O(n * m)

53. 最大子序和

思路

这道题之前我们在讲解贪心专题的时候用贪心算法解决过一次,贪心算法:最大子序和 (opens new window)。

这次我们用动态规划的思路再来分析一次。

动规五部曲如下:

  • 确定dp数组(dp table)以及下标的含义

dp[i]:包括下标i(以nums[i]为结尾)的最大连续子序列和为dp[i]

  • 确定递推公式

dp[i]只有两个方向可以推出来:

  • dp[i - 1] + nums[i],即:nums[i]加入当前连续子序列和
  • nums[i],即:从头开始计算当前连续子序列和

一定是取最大的,所以dp[i] = max(dp[i - 1] + nums[i], nums[i]);

  • dp数组如何初始化

从递推公式可以看出来dp[i]是依赖于dp[i - 1]的状态,dp[0]就是递推公式的基础。

dp[0]应该是多少呢?

根据dp[i]的定义,很明显dp[0]应为nums[0]即dp[0] = nums[0]。

  • 确定遍历顺序

递推公式中dp[i]依赖于dp[i - 1]的状态,需要从前向后遍历。

  • 举例推导dp数组

以示例一为例,输入:nums = [-2,1,-3,4,-1,2,1,-5,4],对应的dp状态如下: 

53.最大子序和(动态规划)

注意最后的结果可不是dp[nums.size() - 1]! ,而是dp[6]。

在回顾一下dp[i]的定义:包括下标i之前的最大连续子序列和为dp[i]。

那么我们要找最大的连续子序列,就应该找每一个i为终点的连续最大子序列。

所以在递推公式的时候,可以直接选出最大的dp[i]。

以上动规五部曲分析完毕,完整代码如下:

class Solution {
    public int maxSubArray(int[] nums) {
        int[] dp = new int[nums.length];
        dp[0] = nums[0];
        int result = dp[0];
        for (int i = 1; i < nums.length; i++) {
            dp[i] = Math.max(dp[i-1]+nums[i],nums[i]);// 状态转移公式
            result = Math.max(result,dp[i]);// result 保存dp[i]的最大值
        }
        return result;
    }
}
  • 时间复杂度:O(n)
  • 空间复杂度:O(n)

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

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

相关文章

LeetCode(12)时间插入、删除和获取随机元素【数组/字符串】【中等】

目录 1.题目2.答案3.提交结果截图 链接&#xff1a; 380. O(1) 时间插入、删除和获取随机元素 1.题目 实现RandomizedSet 类&#xff1a; RandomizedSet() 初始化 RandomizedSet 对象bool insert(int val) 当元素 val 不存在时&#xff0c;向集合中插入该项&#xff0c;并返回…

xss学习笔记

跨站脚本攻击 掌握XSS 的原理 掌握XSS 的场景 掌握XSS 的危害 掌握XSS 漏洞验证 掌握XSS 的分类跨站脚本攻击 漏洞概述 ​ 跨站点脚本&#xff08;Cross Site Scripting&#xff0c; XSS&#xff09;是指客户端代码注入攻击&#xff0c;攻击者可以在合法网站或Web 应用程…

百度文心一言

1分钟了解一言是谁&#xff1f; 一句话介绍【文心一言】 我是百度研发的人工智能模型&#xff0c;任何人都可以通过输入【指令】和我进行互动&#xff0c;对我提出问题或要求&#xff0c;我能高效地帮助你们获取信息、知识和灵感哦 什么是指令&#xff1f;我该怎么和你互动&am…

模拟接口数据之使用Fetch方法实现

文章目录 前言一、package.json配置mock执行脚本二、封装接口&#xff0c;区分走ajax还是fetch三、创建mock目录&#xff0c;及相关接口文件四、定义接口五、使用mock数据使用模拟数据优化fetch返回数据 六、不使用模拟数据七、对比其他需要使用依赖相关配置如有启发&#xff0…

什么叫做云安全?云安全有哪些要求?

云安全(Cloud Security)是一种基于云计算的安全防护策略&#xff0c;旨在保护企业数据和应用程序的安全性和完整性。云安全利用云计算的分布式处理和存储能力&#xff0c;以更高效、更灵活的方式提供安全服务。 云安全的要求主要包括以下几个方面&#xff1a; 数据安全和隐私保…

k8s的service自动发现服务:实战版

Service服务发现的必要性: 对于kubernetes整个集群来说&#xff0c;Pod的地址也可变的&#xff0c;也就是说如果一个Pod因为某些原因退出了&#xff0c;而由于其设置了副本数replicas大于1&#xff0c;那么该Pod就会在集群的任意节点重新启动&#xff0c;这个重新启动的Pod的I…

【python自动化】Playwright基础教程(四)事件操作①高亮元素匹配器鼠标悬停

本文目录 文章目录 前言高亮显示元素定位 - highlighthighlight实战highlight定位多个元素 元素匹配器 - nthnth实战演示 元素匹配 - first&last 综合定位方式时间操作进行实战&#xff0c;巩固之前我们学习的定位方式。 这一部分内容对应官网 : https://playwright.dev/py…

⑦【MySQL】什么是约束?如何使用约束条件?主键、自增、外键、非空....

个人简介&#xff1a;Java领域新星创作者&#xff1b;阿里云技术博主、星级博主、专家博主&#xff1b;正在Java学习的路上摸爬滚打&#xff0c;记录学习的过程~ 个人主页&#xff1a;.29.的博客 学习社区&#xff1a;进去逛一逛~ 约束 ⑦【MySQL】约束条件1. 约束的基本使用2.…

5.运行时数据区-字符串常量池、程序计数器、直接内存

目录 概述字符串常量池字符串常量池存储数据的方式三种常量池字面量与符号引用 哈希表实战 程序计数器直接内存直接内存与堆内存比较 结束 概述 相关文章在此总结如下&#xff1a; 文章地址jvm基本知识地址jvm类加载系统地址双亲委派模型与打破双亲委派地址运行时数据区地址 …

Spring事务之AOP导致事务失效问题

情况说明 首先开启了AOP&#xff0c;并且同时开启了事务。下面这个TransactionAspect就是一个简单的AOP切面&#xff0c;有一个Around通知。 Aspect Component public class TransactionAspect {Pointcut("execution(* com.qhyu.cloud.datasource.service.TransactionSe…

数据结构-链表的简单操作代码实现2【Java版】

目录 写在前&#xff1a; 此篇讲解关于单链表的一些面试题目&#xff0c;续上节。 11.反转一个单链表 12.给定一个带有头结点的head的非空单链表&#xff0c;返回链表的中间结点&#xff0c;如果有两个中间结点&#xff0c;则返回第二个中间结点 13.输入一个链表&#xff0c…

Nginx 使用笔记大全(唯一入口)

Linux服务器因为Nginx日志access.log文件过大项目无法访问 项目处于运行状态下无法访问&#xff0c;第一步查看磁盘状态 1、查看磁盘状态 df -h 2、查找100M以上的文件 find / -size 100M |xargs ls -lh 3、删除文件 rm -rf /usr/local/nginx/logs/access.log 4、配置nginx.…

Linux 性能调优之硬件资源监控

写在前面 考试整理相关笔记博文内容涉及 Linux 硬件资源监控常见的命名介绍&#xff0c;涉及硬件基本信息查看查看硬件错误信息查看虚拟环境和云环境资源理解不足小伙伴帮忙指正 对每个人而言&#xff0c;真正的职责只有一个&#xff1a;找到自我。然后在心中坚守其一生&#x…

centos7下载python3离线安装包

下载离线安装工具 yum install yum-utils -y下载python3离线安装包 yumdownloader --destdir/root/python3 --resolve python3将python3下面的离线安装文件拷贝到其他服务器上就可以安装 离线安装 先进入到离线程序rpm文件存储路径 # 离线安装 rpm -Uvh --force --nodep…

Cnyunwei

运维管理系统&#xff1a;监控系统 Cnyunwei Centos 6 封装 Cacti、Nagios、Centreon&#xff08;中英文自己切换&#xff09;、Check_MK、Nconf英文版本全部采用与国外官方同步的最新版本&#xff0c;会发布32位和64位两个版本。 安装很简单&#xff0c;直接回车即可全自动安…

AttributeError: module ‘matplotlib‘ has no attribute ‘get_data_path‘

【报错】使用 AutoDL 下 Notebook 调用 matplotlib 时遇到 AttributeError: module matplotlib has no attribute get_data_path 报错&#xff1a; --------------------------------------------------------------------------- AttributeError …

《深入浅出进阶篇》——空间换时间优化——P2671 求和

链接&#xff1a;https://www.luogu.com.cn/problem/P2671 上题干&#xff1a; 题目描述 一条狭长的纸带被均匀划分出了n个格子&#xff0c;格子编号从11到n。每个格子上都染了一种颜色colori​用[1,m]当中的一个整数表示&#xff09;&#xff0c;并且写了一个数字numberi​。…

asp.net core mvc之 布局

一、布局是什么&#xff1f; 布局是把每个页面的公共部分&#xff0c;提取成一个布局页面&#xff08;头、导航、页脚&#xff09;。 二、默认布局 _Layout.cshtml 默认的布局是在 /Views/Shared 目录的 _Layout.cshtml文件。通常Shared目录中的视图都是公共视图。该目录下的…

部分背包问题【贪心算法】

部分背包问题是一种经典的贪心问题&#xff0c;物品可以取一部分&#xff0c;也就是可以随意拆分的物品。 算法思路&#xff1a; 用列表保存每个物品的价值及总重量、平均价值&#xff08;性价比&#xff09;。输入数据同时计算每种物品的平均价值。使用自定义的compare函数以…