力扣练习题(2024/4/19)

1两个字符串的删除操作

给定两个单词 word1 和 word2 ,返回使得 word1 和  word2 相同所需的最小步数

每步 可以删除任意一个字符串中的一个字符。

示例 1:

输入: word1 = "sea", word2 = "eat"
输出: 2
解释: 第一步将 "sea" 变为 "ea" ,第二步将 "eat "变为 "ea"

示例  2:

输入:word1 = "leetcode", word2 = "etco"
输出:4

提示:

  • 1 <= word1.length, word2.length <= 500
  • word1 和 word2 只包含小写英文字母

动态规划思路:

  1. 定义 dp[i][j] 为以第 i-1 个字符为结尾的字符串 word1,和以第 j-1 个字符为结尾的字符串 word2,想要达到相等,所需要删除元素的最少次数。

  2. 初始化 dp 数组:

    • 当 word2 为空字符串时,word1 的任意子串都需要删除所有字符才能与之相等,因此 dp[i][0] = i
    • 当 word1 为空字符串时,无论 word2 如何,都不需要删除任何字符,因此 dp[0][j] = 0。这一步在代码中被默认初始化为 0。
  3. 状态转移方程:

    • 当 word1[i - 1] == word2[j - 1],即 word1 的第 i-1 个字符与 word2 的第 j-1 个字符相等时,不需要删除字符,dp[i][j] 可以由 dp[i - 1][j - 1] 继承而来。
    • 当 word1[i - 1] != word2[j - 1],即 word1 的第 i-1 个字符与 word2 的第 j-1 个字符不相等时,此时需要删除字符,dp[i][j] 可以由以下几种操作得到:
      1. 删除 word1 的第 i-1 个字符,转化为以 word1 的前 i-2 个字符与 word2 的前 j-1 个字符相等的状态,操作数加一,即 dp[i][j] = dp[i - 1][j] + 1
      2. 删除 word2 的第 j-1 个字符,转化为以 word1 的前 i-1 个字符与 word2 的前 j-2 个字符相等的状态,操作数加一,即 dp[i][j] = dp[i][j - 1] + 1
      3. 同时删除 word1 的第 i-1 个字符和 word2 的第 j-1 个字符,转化为以 word1 的前 i-2 个字符与 word2 的前 j-2 个字符相等的状态,操作数加二,即 dp[i][j] = dp[i - 1][j - 1] + 2
  4. 最终返回 dp[word1.size()][word2.size()],即以 word1 和 word2 为结尾的字符串相等所需要删除的最少次数。

代码:

class Solution {
public:int minDistance(string word1, string word2) {// 创建二维数组 dp,dp[i][j] 表示将 word1 的前 i 个字符转换为 word2 的前 j 个字符所需的最小操作数vector<vector<int>> dp(word1.size() + 1, vector<int>(word2.size() + 1));// 初始化 dp 数组:当 word2 为空字符串时,需要删除 word1 的所有字符;当 word1 为空字符串时,不需要删除任何字符for (int i = 0; i <= word1.size(); i++) dp[i][0] = i;for (int j = 0; j <= word2.size(); j++) dp[0][j] = j;// 动态规划计算最小操作数for (int i = 1; i <= word1.size(); i++) {for (int j = 1; j <= word2.size(); j++) {if (word1[i - 1] == word2[j - 1]) {// 当前字符相等,不需要额外操作,继承前一个状态的操作数dp[i][j] = dp[i - 1][j - 1];} else {// 当前字符不相等,选择删除 word1 的第 i 个字符或者删除 word2 的第 j 个字符中操作数较小的情况dp[i][j] = min(dp[i - 1][j] + 1, dp[i][j - 1] + 1);}}}// 返回将 word1 转换为 word2 所需的最小操作数return dp[word1.size()][word2.size()];}
};

2 编辑距离

给你两个单词 word1 和 word2, 请返回将 word1 转换成 word2 所使用的最少操作数  。

你可以对一个单词进行如下三种操作:

  • 插入一个字符
  • 删除一个字符
  • 替换一个字符

示例 1:

输入:word1 = "horse", word2 = "ros"
输出:3
解释:
horse -> rorse (将 'h' 替换为 'r')
rorse -> rose (删除 'r')
rose -> ros (删除 'e')

示例 2:

输入:word1 = "intention", word2 = "execution"
输出:5
解释:
intention -> inention (删除 't')
inention -> enention (将 'i' 替换为 'e')
enention -> exention (将 'n' 替换为 'x')
exention -> exection (将 'n' 替换为 'c')
exection -> execution (插入 'u')

提示:

  • 0 <= word1.length, word2.length <= 500
  • word1 和 word2 由小写英文字母组成

思路:

 1. 定义 `dp[i][j]` 表示以下标 i-1 为结尾的字符串 `word1`,和以下标 j-1 为结尾的字符串 `word2`,最近编辑距离为 `dp[i][j]`。

2. 初始化二维数组 `dp`: - 初始化 `dp[i][0] = i`,表示当 `word2` 为空字符串时,将 `word1` 的前 `i` 个字符全部删除即可,操作次数为 `i`。 - 初始化 `dp[0][j] = j`,表示当 `word1` 为空字符串时,将 `word2` 的前 `j` 个字符全部插入即可,操作次数为 `j`。

3. 动态规划求解最小编辑距离: - 对于每个位置 `(i, j)`,如果 `word1[i - 1]` 等于 `word2[j - 1]`,说明当前字符相同,不需要进行操作,取左上角的值 `dp[i - 1][j - 1]`; - 如果当前字符不同,可以选择插入、删除、替换操作中的最小值,并加上一次操作: - `dp[i][j] = min(dp[i - 1][j - 1], dp[i - 1][j], dp[i][j - 1]) + 1`。

4. 最终返回 `dp[word1.size()][word2.size()]`,即将 `word1` 转换成 `word2` 所需的最小操作次数。 这种动态规划的方法利用填表法,逐步计算出最小编辑距离,从而实现字符串之间的匹配和转换。

代码:

class Solution {
public:int minDistance(string word1, string word2) {// 创建二维数组 dp,dp[i][j] 表示将 word1 的前 i 个字符转换成 word2 的前 j 个字符所需的最小操作次数vector<vector<int>> dp(word1.size() + 1, vector<int>(word2.size() + 1, 0));// 初始化 dp 数组的第一行和第一列for(int i = 0; i <= word1.size(); i++) dp[i][0] = i; // word2 为空字符串时,将 word1 的前 i 个字符全部删除即可for(int j = 0; j <= word2.size(); j++)  dp[0][j] = j; // word1 为空字符串时,将 word2 的前 j 个字符全部插入即可// 动态规划求解最小编辑距离for(int i = 1; i <= word1.size(); i++) {for(int j = 1; j <= word2.size(); j++) {if(word1[i - 1] == word2[j - 1]) {dp[i][j] = dp[i - 1][j - 1]; // 当前字符相同,不需要进行操作,取左上角的值} else {// 当前字符不同,可以选择插入、删除、替换操作中的最小值,并加上一次操作dp[i][j] = min({dp[i - 1][j - 1], dp[i - 1][j], dp[i][j - 1]}) + 1;}}}// 返回最小编辑距离return dp[word1.size()][word2.size()];}
};

3回文子串

给你一个字符串 s ,请你统计并返回这个字符串中 回文子串 的数目。

回文字符串 是正着读和倒过来读一样的字符串。

子字符串 是字符串中的由连续字符组成的一个序列。

具有不同开始位置或结束位置的子串,即使是由相同的字符组成,也会被视作不同的子串。

示例 1:

输入:s = "abc"
输出:3
解释:三个回文子串: "a", "b", "c"

示例 2:

输入:s = "aaa"
输出:6
解释:6个回文子串: "a", "a", "a", "aa", "aa", "aaa"

提示:

  • 1 <= s.length <= 1000
  • s 由小写英文字母组成

思路:

首先,我们定义一个二维数组 dp,其中 dp[i][j] 表示字符串 s 中以索引 i 开始、索引 j 结束的子串是否为回文串。初始化时,我们将所有 dp[i][j] 的值设为 false,表示初始时所有子串都不是回文串。

然后,我们从字符串的末尾开始向前遍历,这样我们可以先计算出小区间的结果,再利用小区间的结果计算大区间的结果。对于每个索引 i,我们再从 i 开始向后遍历,对于每个索引 j,我们判断 s[i] 是否等于 s[j]

  • 如果 s[i] 等于 s[j],则可能存在回文子串。我们进一步分析:
    1. 如果 j - i 小于等于 1,说明子串长度为 1 或 2,此时 s[i] 和 s[j] 相等,所以子串是回文串,我们将结果加一,并将 dp[i][j] 设为 true
    2. 如果 j - i 大于 1,且 dp[i + 1][j - 1] 为 true,说明内部子串是回文串,且 s[i] 和 s[j] 相等,此时整个子串也是回文串,我们将结果加一,并将 dp[i][j] 设为 true

最终,我们返回计算得到的回文子串的数量。

代码

class Solution {
public:int countSubstrings(string s) {// 创建二维数组 dp,dp[i][j] 表示 s 中以索引 i 开始、索引 j 结束的子串是否为回文串vector<vector<bool>> dp(s.size(), vector<bool>(s.size(), false));int result = 0;// 从后向前遍历字符串 s,保证先计算出小区间的结果,再利用小区间的结果计算大区间的结果for (int i = s.size() - 1; i >= 0; i--) {for (int j = i; j < s.size(); j++) {if (s[i] == s[j]) {if (j - i <= 1) { // 情况一:子串长度为 1 或 2result++; // 单个字符或相邻字符构成的子串都是回文串dp[i][j] = true;} else if (dp[i + 1][j - 1]) { // 情况二:子串长度大于 2,且内部子串是回文串result++; // 内部子串是回文串,且两端字符相同,则整个子串也是回文串dp[i][j] = true;}}}}// 返回回文子串的数量return result;}
};

4. 最长回文子序列

给你一个字符串 s ,找出其中最长的回文子序列,并返回该序列的长度。

子序列定义为:不改变剩余字符顺序的情况下,删除某些字符或者不删除任何字符形成的一个序列。

示例 1:

输入:s = "bbbab"
输出:4
解释:一个可能的最长回文子序列为 "bbbb" 。

示例 2:

输入:s = "cbbd"
输出:2
解释:一个可能的最长回文子序列为 "bb" 。

提示:

  • 1 <= s.length <= 1000
  • s 仅由小写英文字母组成

思路:

  1. 定义状态: 首先,我们需要定义动态规划状态。在这里,我们使用二维数组 dp[i][j],其中 dp[i][j] 表示从字符串 s 的下标 i 到 j 之间的子串中的最长回文子序列长度。

  2. 状态转移方程: 接下来,我们需要找到状态之间的转移关系。当我们在考虑 dp[i][j] 时,我们可以根据 s[i] 和 s[j] 的关系来决定如何更新 dp[i][j] 的值:

    • 如果 s[i] == s[j],那么 dp[i][j] 可以由 dp[i + 1][j - 1] 推导而来,即 dp[i][j] = dp[i + 1][j - 1] + 2,因为两端相同的字符可以增加最长回文子序列的长度。
    • 如果 s[i] != s[j],那么 dp[i][j] 可以由 dp[i + 1][j] 和 dp[i][j - 1] 中的较大值推导而来,因为当前位置的字符不同,所以无法直接形成回文,只能取相邻子串中的最长回文子序列的长度作为当前子串的最长回文子序列长度,即 dp[i][j] = max(dp[i + 1][j], dp[i][j - 1])
  3. 初始化: 我们需要对动态规划数组进行初始化。对角线上的元素 dp[i][i] 表示单个字符的子串为回文子序列,因此初始化为 1。

  4. 状态转移计算: 我们从字符串的末尾开始向前遍历,逐步计算出每个子串的最长回文子序列长度,直到计算出整个字符串的最长回文子序列长度。

  5. 返回结果: 最后,我们返回 dp[0][s.size() - 1],即整个字符串的最长回文子序列长度

代码:

class Solution {
public:int longestPalindromeSubseq(string s) {// 创建二维数组 dp,dp[i][j] 表示以下标 i 到 j 之间的子串中的最长回文子序列长度vector<vector<int>> dp(s.size(), vector<int>(s.size(), 0));// 初始化 dp 数组的对角线,即单个字符的子串为回文子序列,长度为 1for (int i = 0; i < s.size(); i++) dp[i][i] = 1;// 动态规划求解最长回文子序列长度for (int i = s.size() - 1; i >= 0; i--) {for (int j = i + 1; j < s.size(); j++) {if (s[i] == s[j]) {dp[i][j] = dp[i + 1][j - 1] + 2; // 当前字符相同,加上两端字符的最长回文子序列长度} else {dp[i][j] = max(dp[i + 1][j], dp[i][j - 1]); // 当前字符不同,取相邻子串中的最长回文子序列长度}}}// 返回整个字符串的最长回文子序列长度return dp[0][s.size() - 1];}
};

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

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

相关文章

(一)、SQL进阶——神奇的SQL

一、CASE表达式 1、CASE表达式概述 case表达式有简单case表达式和搜索case表达式两种写法 -- 简单case表达式 case sex when 1 then 男 when 0 then 女 else 其他 end -- 搜索case表达式 case when sex1 then 男 when sex1 then 男 else 其他 end 这两种写法执行的结…

跨平台手机号:微信手机号授权登录、微信授权登录双登录实现账户生态融合,新时代的身份密钥

小程序厂商的多样性体现在开发工具、服务领域、商业模式等多方面&#xff0c;各厂商凭借独特的技术优势、行业解决方案和市场策略&#xff0c;满足不同企业和用户需求。与此同时&#xff0c;随着移动互联网发展&#xff0c;手机号统一登录成为提升用户体验、简化登录流程的关键…

每日一篇 4.24(提前)

condemns :谴责 Claim&#xff1a;说法 malicious&#xff1a;恶意 curb&#xff1a;遏制 stabilization of xxx ties&#xff1a;xx关系稳定 launched its harshest attack to date on xxx&#xff1a;发起了迄今为止最严厉的攻击 suppressing&#xff1a;打压 favorable…

Go语言接口使用

底层值为 nil 的接口值 即便接口内的具体值为 nil&#xff0c;方法仍然会被 nil 接收者调用。 在一些语言中&#xff0c;这会触发一个空指针异常&#xff0c;但在 Go 中通常会写一些方法来优雅地处理它&#xff08;如本例中的 M 方法&#xff09;。 注意: 保存了 nil 具体值…

要养生也要时尚,益百分满足你的所有需求

要养生也要时尚&#xff0c;益百分满足你的所有需求 艾灸是个好东西&#xff0c;尤其是在近几年的时候&#xff0c;艾灸就像一阵浪潮席卷进了人们的日常生活之中&#xff0c;我们可以在街边看到大大小小的艾灸馆&#xff0c;有些评价比较高的艾灸馆门前甚至还排起了长长的队伍…

Unity3D 分块编辑小AStar地图详解

前言 A算法是一种经典的寻路算法&#xff0c;能够帮助游戏中的角色找到最短路径。在本文中&#xff0c;我们将介绍如何在Unity3D中使用分块编辑的方式创建一个小的A地图&#xff0c;并实现A*算法来实现角色的寻路。 对惹&#xff0c;这里有一个游戏开发交流小组&#xff0c;希…

FasterViT:英伟达提出分层注意力,构造高吞吐CNN-ViT混合网络 | ICLR 2024

论文设计了新的CNN-ViT混合神经网络FasterViT&#xff0c;重点关注计算机视觉应用的图像吞吐能力。FasterViT结合CNN的局部特征学习的特性和ViT的全局建模特性&#xff0c;引入分层注意力&#xff08;HAT&#xff09;方法在降低计算成本的同时增加窗口间的交互。在包括分类、对…

【InternLM 实战营第二期笔记】Lagent AgentLego 智能体应用搭建

理论知识 Lagent 是什么 Lagent 是一个轻量级开源智能体框架&#xff0c;旨在让用户可以高效地构建基于大语言模型的智能体。同时它也提供了一些典型工具以增强大语言模型的能力。 Lagent 目前已经支持了包括 AutoGPT、ReAct 等在内的多个经典智能体范式&#xff0c;也支持了…

主流微前端框架对比与选择策略

微前端是一种架构风格&#xff0c;旨在将大型前端应用程序拆分为多个独立的模块&#xff0c;这些模块可以独立开发、测试和部署。主流的微前端框架有以下几种&#xff1a; Single-SPA&#xff1a;Single-SPA 是一个超级父级框架&#xff0c;可以与其他前端框架集成&#xff0c;…

linux环境变量设置

windows环境变量设置步骤&#xff1a; 右键"我的电脑"高级设置环境变量编辑"用户变量"或者"系统变量" linux下环境变量的设置步骤&#xff1a; 修改/etc/profile添加如下格式条目&#xff1a; export MAVEN_HOME/usr/local/apache-maven-3.6…

C语言指针+-整数、指针-指针、指针关系运算、指针和数组、二级指针、指针数组

文章目录 前言一、指针 - 整数二、指针 - 指针三、指针的关系运算四、指针和数组五、二级指针六、指针数组指针数组可以将几个一维数组模拟成二维数组 总结 前言 C语言指针整数、指针-指针、指针关系运算、指针和数组、二级指针、指针数组等介绍&#xff0c;还包括指针数组将几…

武汉大学博士,华为上班5年多,月薪多少。。。

最近&#xff0c;一位来自武汉大学的博士研究生透露了自己在华为公司工作五年后的薪酬情况。 据他透露&#xff0c;他在2018年加入华为时的月薪为2.4万&#xff0c;随着时间的推移&#xff0c;到了2023年&#xff0c;他的月薪已经增长至4.4万&#xff01;此外&#xff0c;他还透…

工作后的自我介绍

您好&#xff0c;我叫Li&#xff0c;毕业于双一流**大学软件工程专业。 在大学期间通过四级&#xff0c;获得计算机C语言二级证书、科技立项奖&#xff08;词频统计&#xff09;、国家励志奖学金、优秀学生奖学金、优秀团干部、新生奖学金等。在校主修的课程有C、Java、数据结…

AI时代的GPU集群网络算力分析

浅谈GPU集群网络、集群规模和集群算力 引言在生成式AI&#xff08;GenAI&#xff09;和大模型时代&#xff0c;不仅需要关注单个GPU卡的算力&#xff0c;更要关注GPU集群的总有效算力。单个GPU卡的有效算力可以通过该卡的峰值算力来测算&#xff0c;例如&#xff0c;对于Nvidia…

class093 贪心经典题目专题5【左程云算法】

class093 贪心经典题目专题5【左程云算法】 前言版权推荐class093 贪心经典题目专题5最后 前言 2024-4-23 14:01:18 以下内容源自《【左程云算法】》 仅供学习交流使用 版权 禁止其他平台发布时删除以下此话 本文首次发布于CSDN平台 作者是CSDN日星月云 博客主页是https://…

网络工程师----第十一天

OSPF&#xff1a; 对称加密算法&#xff1a; 也称为私钥加密或单密钥算法&#xff0c;是一种加密方式&#xff0c;其中加密和解密使用相同的密钥。这种算法的优点包括加密解密速度快、计算量小&#xff0c;适用于大量数据的加密。然而&#xff0c;它的缺点是密钥的安全性难以保…

SEHLL脚本编程---- Nginx日志分析6-统计每分钟的请求数

描述 假设Nginx的日志存储在nowcoder.txt里&#xff0c;内容如下&#xff1a; 192.168.1.20 - - [21/Apr/2020:14:12:49 0800] "GET /1/index.php HTTP/1.1" 404 490 "-" "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:45.0) Gecko/20100101 Firefo…

深度相机(3D相机)

传统的RGB彩色相机称为2D相机&#xff0c; 只能得到2D的图像信息&#xff0c; 无法得到物体与相机的距离信息&#xff0c;也就是深度信息。 顾名思义&#xff0c; 深度相机除了获取2D信息&#xff0c;还能得到深度信息&#xff0c;也叫RGBD相机&#xff0c; 或3D相机。 顺便提…

被删除的照片和视频能找回吗?如何恢复手机删除的照片和视频?

手机里的照片和视频是我们记录生活的每一个瞬间&#xff0c;也是工作学习等场合经常用到的东西&#xff0c;一旦不慎丢失&#xff0c;将对我们造成很大损失。那么我们该如何恢复手机删除的照片和视频呢&#xff1f;通过掌握正确的恢复方法&#xff0c;能够最大程度地保护手机中…

网络常识!!!

网络常识!!! 一:网络的发展史二:关键的概念三:IP地址四:端口号二级目录二级目录二级目录二级目录三级目录 一:网络的发展史 从游戏方面发展历程进行理解: 从单机游戏-----游戏支持局域网对战-------游戏支持广域网对战-------移动端 (1)局域网对战:在同一个网吧里,不同的游戏…