【二分查找】【双指针】LeetCode:2565最少得分子序列

作者推荐

【动态规划】【广度优先】LeetCode2258:逃离火灾

本文涉及的基础知识点

二分查找算法合集 有序向量的二分查找,初始化完成后,向量不会修改。
双指针: 用于计算子字符串是s的字符串的子系列。

题目

给你两个字符串 s 和 t 。
你可以从字符串 t 中删除任意数目的字符。
如果没有从字符串 t 中删除字符,那么得分为 0 ,否则:
令 left 为删除字符中的最小下标。
令 right 为删除字符中的最大下标。
字符串的得分为 right - left + 1 。
请你返回使 t 成为 s 子序列的最小得分。
一个字符串的 子序列 是从原字符串中删除一些字符后(也可以一个也不删除),剩余字符不改变顺序得到的字符串。(比方说 “ace” 是 “abcde” 的子序列,但是 “aec” 不是)。
示例 1:
输入:s = “abacaba”, t = “bzaa”
输出:1
解释:这个例子中,我们删除下标 1 处的字符 “z” (下标从 0 开始)。
字符串 t 变为 “baa” ,它是字符串 “abacaba” 的子序列,得分为 1 - 1 + 1 = 1 。
1 是能得到的最小得分。
示例 2:
输入:s = “cde”, t = “xyz”
输出:3
解释:这个例子中,我们将下标为 0, 1 和 2 处的字符 “x” ,“y” 和 “z” 删除(下标从 0 开始)。
字符串变成 “” ,它是字符串 “cde” 的子序列,得分为 2 - 0 + 1 = 3 。
3 是能得到的最小得分。
参数范围
1 <= s.length, t.length <= 105
s 和 t 都只包含小写英文字母。

分析

时间复杂度😮(nlogn)。枚举tRight,时间复杂度O(n);二分查找tLeft,时间复杂度O(logn)。令m_c是t的长度。tLeft=left-1,tRight=right+1。

变量解析

vLeft[i]=x表示t[0,i]是s[0,x]子序列,x如果有多个值取最小值。如果x不存在,为任意大于等于m_c的值。显然是升序。
vRight[i]=x表示t[t…)是s[x,…)子序列,如果x有多个值取最大值。如果x不存在,为任意小于0的值。

原理

将left和right直接的元素全部删除,积分不会增加,所以全删除。全删除后,只有两种情况:一,不删除。二,删除一处。t由两个部分组成。[0,tLeft]和[tRight,m_c)。如果左边为空,tLeft为-1;如果右边为空,tRight为m_c。sRight 为vRight[tRight],sLeft是小于sRight中的最大值。这样确保[0,sLeft]和[sRight…)没有重叠部分。sLeft在vLeft中的下标就是tLeft,tLeft必须小于tRight,否则[0,tLeft]和[tRight,m_c)会有重叠部分。

特殊情况

右边为空,在初始化vRight的时候,需要特殊处理,后续操作不需要。
如果vRight[tRight]非法,需要忽略。
tLeft为-1,不需特殊处理,就是左边为空。

代码

核心代码

class Solution {
public:int minimumScore(string s, string t) {m_c = t.length();//vLeft[i]=x,表示t[0,i]是s[0,x]子序列,x如果有多个值取最小值。如果x不存在,为任意大于等于m_c的值//vRight[i]=x,表示t[t...)是s[x,...)子序列,如果x有多个值取最大值。如果x不存在,为任意小于0的值。vector<int> vLeft(m_c, m_c),vRight(m_c,-1);{for (int i = 0, right=0; i < m_c; i++){while ((right < s.length()) && (s[right] != t[i])){right++;}vLeft[i] = right++;}}{for (int i = m_c - 1,left=s.length()-1; i >= 0; i--){while ((left >= 0) && (s[left] != t[i])){left--;}vRight[i] = left--;}}int iRet = m_c;vRight.emplace_back(s.length());//(right,m_c)为空不需要做特殊处理for (int tRight = 0 ; tRight < vRight.size(); tRight++){const auto& sRight = vRight[tRight];if (sRight < 0){continue;}//寻找第一个小于vRight[right]的索引int tLeft = std::lower_bound(vLeft.begin(), vLeft.end(), sRight)- vLeft.begin()-1;tLeft = min(tLeft, tRight - 1);iRet = min(iRet, tRight - tLeft - 1);}		return iRet;}int m_c;
};

测试用例

template<class T>
void Assert(const vector<T>& v1, const vector<T>& v2)
{if (v1.size() != v2.size()){assert(false);return;}for (int i = 0; i < v1.size(); i++){assert(v1[i] == v2[i]);}
}template<class T>
void Assert(const T& t1, const T& t2)
{assert(t1 == t2);
}int main()
{string s, t;	{Solution slu;s = "abacaba", t = "bzaa";auto res = slu.minimumScore(s, t);Assert(1, res);}{Solution slu;s = "cde", t = "xyz";auto res = slu.minimumScore(s, t);Assert(3, res);}{Solution slu;s = "adebddaccdcabaade", t = "adbae";auto res = slu.minimumScore(s, t);Assert(0, res);}{Solution slu;s = "eceecbabe", t = "bdeaec";auto res = slu.minimumScore(s, t);Assert(4, res);}//CConsole::Out(res);
}

优化

第二轮循环,可以和第三轮循环合并,且改成双指针。可以直接用栈(向量)的出栈代替指针。第一轮寻找改成枚举s,更方便。

class Solution {
public:int minimumScore(string s, string t) {m_c = t.length();vector<int> vLeft;for (int is = 0; is < s.length(); is++){if ((vLeft.size() < m_c) && (s[is] == t[vLeft.size()])){vLeft.emplace_back(is);}}int iRet = m_c - vLeft.size(); //tRight==m_cfor (int tRight = m_c - 1,sRight = s.length()-1 ; tRight >= 0; tRight--){while ((sRight >= 0) && (s[sRight] != t[tRight])){sRight--;}if (sRight < 0){break;}while (vLeft.size() &&((vLeft.back() >= sRight) || (vLeft.size() > tRight))){vLeft.pop_back();}iRet = min(iRet, tRight - (int)vLeft.size());sRight--;}	return iRet;}int m_c;
};

2023年3月旧代码

class Solution {
public:
int minimumScore(string s, string t) {
m_c = t.length();
m_c2 = s.length();
m_vLeft.assign(m_c, m_c2);
m_vRight.assign(m_c, -1);
{
int j = 0;
for (int i = 0; i < m_c; i++)
{
while ((j < m_c2) && (s[j] != t[i]))
{
j++;
}
if (s.length() == j)
{
break;
}
m_vLeft[i] = j++;
}
}
{
int j = s.length()-1 ;
for (int i = m_c - 1; i >= 0; i–)
{
while ((j >= 0 ) && (s[j] != t[i]))
{
j–;
}
if (-1 == j)
{
break;
}
m_vRight[i] = j–;
}
}
int left = -1, right = m_c;
for (; left + 1 != right;)
{
const int len = (left + right) / 2;
if (Can(len))
{
right = len;
}
else
{
left = len;
}
}
return right;
}
bool Can(int len)
{
for (int i = 0; i + len - 1 < m_c; i++)
{
bool bCan = true;
if (i + len == m_c)
{
bCan = m_vLeft[i - 1] < m_c2;
}
else if (0 == i)
{
bCan = m_vRight[i + len] > -1;
}
else
{
bCan = m_vLeft[i - 1] < m_vRight[i + len];
}
if (bCan)
{
return true;
}
}
return false;
}
vector m_vLeft, m_vRight;
int m_c;
int m_c2;
};

扩展阅读

视频课程

有效学习:明确的目标 及时的反馈 拉伸区(难度合适),可以先学简单的课程,请移步CSDN学院,听白银讲师(也就是鄙人)的讲解。
https://edu.csdn.net/course/detail/38771

如何你想快

速形成战斗了,为老板分忧,请学习C#入职培训、C++入职培训等课程
https://edu.csdn.net/lecturer/6176

相关

下载

想高屋建瓴的学习算法,请下载《喜缺全书算法册》doc版
https://download.csdn.net/download/he_zhidan/88348653

我想对大家说的话
闻缺陷则喜是一个美好的愿望,早发现问题,早修改问题,给老板节约钱。
子墨子言之:事无终始,无务多业。也就是我们常说的专业的人做专业的事。
如果程序是一条龙,那算法就是他的是睛

测试环境

操作系统:win7 开发环境: VS2019 C++17
或者 操作系统:win10 开发环境: VS2022 C++17
如无特殊说明,本算法用**C++**实现。

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

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

相关文章

《地理信息系统原理》笔记/期末复习资料(10. 空间数据挖掘与空间决策支持系统)

目录 10. 空间数据挖掘与空间决策支持系统 10.1. 空间数据挖掘 10.1.1. 空间数据挖掘的概念 10.1.2. 空间数据挖掘的方法与过程 10.1.3. 空间数据挖掘的应用 10.2. 空间决策支持系统 10.2.1. 空间决策支持系统的概念 10.2.2. 空间决策支持系统的结构 10.2.3. 空间决策…

基于chaos混沌的彩色图像加解密系统matlab仿真

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 4.1 混沌理论简介 4.2 基于混沌的图像加密原理 4.3 数学公式与实现过程 5.算法完整程序工程 1.算法运行效果图预览 2.算法运行软件版本 matlab2022a 3.部分核心程序 .................…

记录将C语言编写的Windows程序转换为python语言编写,演示具体效果在最后,这对初学者理解Windows消息机制及框架有一定参考作用

主要思路 由于C语言的数组定义使用名字加中括号及括号内数字定义&#xff0c;但是在python中【】已经被作为列表 元组等序列类型分片、存取元素&#xff0c;因此我们不能像C语言那样定义数组 例如C语言 int a[10] 是声明定义一个含有10个int类型的数组a,而在执行语句部分…

华为OD机试真题B卷 Java 实现【统计大写字母个数】,附详细解题思路

一、题目描述 找出给定字符串中大写字符(即’A’-‘Z’)的个数。 数据范围&#xff1a;字符串长度&#xff1a;1≤∣s∣≤250 字符串中可能包含空格或其他字符 二、输入描述 对于每组样例&#xff0c;输入一行&#xff0c;代表待统计的字符串。 三、输出描述 输出一个整…

【css】css实现文字两端对齐效果:

文章目录 一、方法1&#xff1a;二、方法2&#xff1a;三、注意&#xff1a; 一、方法1&#xff1a; 给元素设置 text-align: justify;text-align-last: justify;并且加上text-justify: distribute-all-line; 目的是兼容ie浏览器 p{width: 130px;text-align: justify;text-alig…

飞天使-linux操作的一些技巧与知识点3-http的工作原理

文章目录 http工作原理nginx的正向代理和反向代理的区别一个小技巧dig 命令巧用 http工作原理 http1.0 协议 使用的是短连接&#xff0c;建立一次tcp连接&#xff0c;发起一次http的请求&#xff0c;结束&#xff0c;tcp断开 http1.1 协议使用的是长连接&#xff0c;建立一次tc…

Network 灰鸽宝典【目录】

目前已有文章 21 篇 Network 灰鸽宝典专栏主要关注服务器的配置&#xff0c;前后端开发环境的配置&#xff0c;编辑器的配置&#xff0c;网络服务的配置&#xff0c;网络命令的应用与配置&#xff0c;windows常见问题的解决等。 文章目录 服务配置环境部署GitNPM 浏览器编辑器系…

GEE:重分类

作者:CSDN @ _养乐多_ 本文记录了在 Google Earth Engine(GEE)平台上对一副类别图像进行重分类的代码。并以 COPERNICUS/Landcover/100m/Proba-V-C3/Global 数据集中的土地利用数据为例。 结果如下图所示, 文章目录 一、核心函数二、示例代码三、代码链接一、核心函数 核…

文件操作及函数

什么是文件&#xff1f; 在程序设计中&#xff0c;文件有两种&#xff1a;程序文件和数据文件。 程序文件 包括源程序文件&#xff08;.c&#xff09;&#xff0c;目标文件&#xff08;.obj&#xff09;&#xff0c;可执行程序(.exe)。 数据文件 文件的内容不一定是程序&…

linux下部署frp客户端服务端-内网穿透

简介 部署在公司内部局域网虚拟机上的服务需要在外网能够访问到&#xff0c;这不就是内网穿透的需求吗&#xff0c;之前通过路由器实现过&#xff0c;现在公司这块路由器不具备这个功能了&#xff0c;目前市面上一些主流的内网穿透工具有&#xff1a;Ngrok&#xff0c;Natapp&…

Docker镜像构建:深入Dockerfile创建自定义镜像

Docker的强大之处在于其能够通过Dockerfile定义和构建自定义镜像&#xff0c;为应用提供独立、可移植的运行环境。在这篇博客文章中&#xff0c;将深入探讨Docker镜像构建的核心概念&#xff0c;通过更加丰富的示例代码&#xff0c;帮助大家全面理解和掌握构建自定义镜像的技术…

深度学习在人体动作识别领域的应用:开源工具、数据集资源及趋动云GPU算力不可或缺

人体动作识别检测是一种通过使用计算机视觉和深度学习技术&#xff0c;对人体姿态和动作进行实时监测和分析的技术。该技术旨在从图像或视频中提取有关人体姿态、动作和行为的信息&#xff0c;以便更深入地识别和理解人的活动。 人体动作识别检测的基本步骤包括&#xff1a; 数…

关于MySQL的bigint问题

MySQL的bigint(8)能存多大数值&#xff1f; MySQL的BIGINT(8)可以存储的数值范围是从-9,223,372,036,854,775,808到9,223,372,036,854,775,807。这是因为BIGINT数据类型在MySQL中使用8字节进行存储&#xff0c;每个字节有8位&#xff0c;所以总共可以表示2^64个不同的整数。 …

IDEA 出现问题:git提交commit时Perform code analysis卡住解决方案

问题 git提交commit时Perform code analysis卡住很久 解决方案一 1、打开 IntelliJ IDEA&#xff0c;进入 File -> Settings&#xff08;或者使用快捷键 CtrlAltS&#xff09;。 2、在弹出的 Settings 窗口中&#xff0c;找到 Version Control -> Commit Dialog 选项…

什么是数字化营销?如何进行数字化营销?数字化有多重要?

引言 数字化营销是一种利用数字技术和在线平台来促进产品或服务销售的策略。它包括利用各种数字渠道&#xff0c;如社交媒体、搜索引擎优化、内容营销和数据分析等&#xff0c;与目标受众建立联系并推动销售。 在当今商业环境中&#xff0c;数字化营销扮演着至关重要的角色。…

阿里云国际版无法远程连接Windows服务器的排查方法

如果您遇到紧急情况&#xff0c;需要尽快登录Windows实例&#xff0c;请参见以下操作步骤&#xff0c;先检查ECS实例的状态&#xff0c;然后通过云助手向Windows实例发送命令或通过VNC登录实例&#xff0c;具体步骤如下&#xff1a; 步骤一&#xff1a;检查ECS实例状态 无论何…

SpringBoot之请求的详细解析

1. 请求 在本章节呢&#xff0c;我们主要讲解&#xff0c;如何接收页面传递过来的请求数据。 1.1 Postman 之前我们课程中有提到当前最为主流的开发模式&#xff1a;前后端分离 在这种模式下&#xff0c;前端技术人员基于"接口文档"&#xff0c;开发前端程序&…

智能优化算法应用:基于萤火虫算法3D无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于萤火虫算法3D无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于萤火虫算法3D无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.萤火虫算法4.实验参数设定5.算法结果6.参考文…

Unity检测AssetBundle是否循环依赖

原理&#xff1a;bundle的依赖关系构建一个二维的矩阵图&#xff0c;如果对角线相互依赖&#xff08;用1标记&#xff09;则表示循环依赖。 using PlasticGui; using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEditor; public cl…

单变量线性回归的机器学习代码

本文为学习吴恩达版本机器学习教程的代码整理&#xff0c;使用的数据集为https://github.com/fengdu78/Coursera-ML-AndrewNg-Notes/blob/f2757f85b99a2b800f4c2e3e9ea967d9e17dfbd8/code/ex1-linear%20regression/ex1data1.txt 将数据集和py代码放到同一目录中&#xff0c;使…