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

news2024/12/29 10:38:51

作者推荐

【动态规划】【广度优先】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_c
		for (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.coloradmin.cn/o/1306043.html

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

相关文章

19.java绘图

A.Graphics类 Graphics类是java.awt包中的一个类&#xff0c;它用于在图形用户界面&#xff08;GUI&#xff09;或其他图形应用程序中进行绘制。该类通常与Component的paint方法一起使用&#xff0c;以在组件上进行绘制操作。 一些Graphics类的常见用法和方法&#xff1a; 在组…

Java基础语法之类和对象

类的定义 类就是对一个实体的属性功能进行描述 类的定义格式 首先要用到class关键字&#xff1b; 其次&#xff0c;类名采用大驼峰形式例如Dog ClassName Student…… 最后&#xff0c;类中包含该类的属性&#xff0c;即成员变量&#xff1b;以及该类的功能&#xff0…

HelpLook VS Confluence:知识管理方面谁更有优势?

多年来&#xff0c;在线协作和文档工具市场一直被Confluence所主导。Confluence由Atlassian于2004年创立&#xff0c;很迅速地成为企业寻求强大而全面的协作解决方案和知识管理的热门选择。然而&#xff0c;随着新工具如Notion和HelpLook的出现&#xff0c;市场格局发生了变化&…

各地加速“双碳”落地,数字能源供应商怎么选?

作者 | 曾响铃 文 | 响铃说 随着我国力争2030年前实现“碳达峰”、2060年前实现“碳中和”的“双碳”目标提出&#xff0c;为各地区、各行业的低碳转型和绿色可持续发展制定“倒计时”时间表&#xff0c;一场围绕“数字能源”、“智慧能源”、“新能源”等关键词的创新探索进…

十六 动手学深度学习v2计算机视觉 ——样式迁移

文章目录 基于CNN的样式迁移 基于CNN的样式迁移 我们通过前向传播&#xff08;实线箭头方向&#xff09;计算风格迁移的损失函数&#xff0c;并通过反向传播&#xff08;虚线箭头方向&#xff09;迭代模型参数&#xff0c;即不断更新合成图像。 风格迁移常用的损失函数由3部分组…

【lombok】从easyExcel read不到值到cglib @Accessors(chain = true)隐藏的大坑

背景: 在一次使用easyExcel.read 读取excel时&#xff0c;发现实体类字段没有值&#xff0c;在反复测试后&#xff0c;发现去掉Accessors(chain true)就正常了&#xff0c;为了验证原因&#xff0c;进行了一次代码跟踪 由于调用链路特别长&#xff0c;只列举出部分代码&#x…

141 环形链表

解题思路&#xff1a; \qquad 最容易想到的方法&#xff0c;就是遍历链表同时用哈希表unordered_map把节点存下来&#xff1a; \qquad\qquad 遇到重复节点则认为存在环&#xff0c;返回true&#xff1b; \qquad\qquad 遍历到nullptr&#xff0c;则链表中不存在环&#xff0c…

使命召唤9缺少buddha.dll的解决方法分享,如何快速修复buddha.dll

《使命召唤》系列作为备受欢迎的第一人称射击游戏,经常会在新作发行后引起广大玩家的讨论。最近&#xff0c;《使命召唤9》玩家中出现了一个常见的技术问题&#xff1a;游戏无法启动&#xff0c;因为系统找不到 buddha.dll 文件。这篇文章将探讨 buddha.dll 的相关信息、丢失原…

奥比中光 Femto Bolt相机ROS配置

机械臂手眼标定详解 作者&#xff1a; Herman Ye Auromix 测试环境&#xff1a; Ubuntu20.04/22.04 、ROS1 Noetic/ROS2 Humble、X86 PC/Jetson Orin、Kinect DK/Femto Bolt 更新日期&#xff1a; 2023/12/12 注1&#xff1a; Auromix 是一个机器人爱好者开源组织。 注2&#…

机器学习笔记 - 基于C# + .net framework 4.8的ONNX Runtime进行分类推理

该示例是从官方抄的,演示了如何使用 Onnx Runtime C# API 运行预训练的 ResNet50 v2 ONNX 模型。 我这里的环境基于.net framework 4.8的一个winform项目,主要依赖下面版本的相关库。 Microsoft.Bcl.Numerics.8.0.0 Microsoft.ML.OnnxRuntime.Gpu.1.16.3 SixLabors.ImageShar…

“百里挑一”AI原生应用亮相,百度智能云千帆AI加速器首个Demo Day来了!

作者简介&#xff1a; 辭七七&#xff0c;目前大二&#xff0c;正在学习C/C&#xff0c;Java&#xff0c;Python等 作者主页&#xff1a; 七七的个人主页 文章收录专栏&#xff1a; 七七的闲谈 欢迎大家点赞 &#x1f44d; 收藏 ⭐ 加关注哦&#xff01;&#x1f496;&#x1f…

机器视觉系统选型-同轴光源分类及应用场景

同轴光源 从与相机同轴的方向均匀照射漫射光 Mark点定位条码识别二维码识别反光物体表面缺陷检测 高亮同轴光源 照射光线与水平方向成低角度夹角Mark点定位反光件表面凹坑、损伤、缺陷印刷电路板二维码识别 平行同轴光源 从与相机同轴方向照射平行度高 的平行光尺寸测量玻璃检…

Linux---Ubuntu操作系统

1. Ubuntu操作系统的介绍 Ubuntu操作系统是属于Linux操作系统中的一种&#xff0c;它是免费、稳定又可以拥有绚丽界面的一个操作系统 2. Ubuntu图形界面的介绍 任务栏 窗口操作按钮 窗口菜单条 任务栏效果图: 窗口操作按钮效果图: 窗口菜单条效果图: 3. 与Windows目录结…

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

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

HarmonyOS(二)—— 初识ArkTS开发语言(下)之ArkTS声明式语法和组件化基础

前言&#xff1a; 通过前面ArkTS开发语言&#xff08;上&#xff09;之TypeScript入门以及ArkTS开发语言&#xff08;中&#xff09;之ArkTS的由来和演进俩文我们知道了ArkTS的由来以及演进&#xff0c;知道了ArkTS具备了声明式语法和组件化特性&#xff0c;今天&#xff0c;搭…

计网 - 如何理解 Mac地址 、 IP地址 、端口号

文章目录 概述Mac地址IP 地址IP 地址和 MAC 地址之间的区别端口号为什么端口号有 65535 个&#xff1f;端口号的确定标准既定的端口号时序分配法 观察端口号 小结 概述 Mac地址&#xff08;Media Access Control Address&#xff09;和IP地址&#xff08;Internet Protocol Ad…

蓝桥杯小白赛第一场(1~6)(期望DP)

1、模拟 2、贪心 3、前缀和 4、猜结论 5、双指针 6、期望DP 1. 蘑菇炸弹 思路&#xff1a;一个简单的暴力模拟。 #include <bits/stdc.h> using namespace std; int main() {int n;cin >> n;vector<int>a(n , 0);for(int i 0 ; i < n ; i )cin &…

西南交通大学【数据结构实验8】

实验内容及要求&#xff1a; 编写控制台应用程序&#xff0c;提供以下菜单项&#xff1a; 插入元素 从键盘输入若干两两互不相同的非0整数&#xff0c;直到输入0时停止。将输入的所有非0整数按输入次序插入二叉排序树(初始时是空树)。 插入某个非0整数时&#xff0c;若该整…

Linux——基本指令(二)

​ 个人主页&#xff1a;日刷百题 系列专栏&#xff1a;〖C语言小游戏〗〖Linux〗〖数据结构〗 〖C语言〗 &#x1f30e;欢迎各位→点赞&#x1f44d;收藏⭐️留言&#x1f4dd; ​ ​ 写在前面&#xff1a; 紧接上一章&#xff0c;我们在理解接下来的命令之前&#xff0c…

IEEE Transactions on Industrial Electronics工业电子TIE论文投稿须知

一、背景 IEEE TIE作为控制领域的TOP期刊&#xff0c;接收机器人、控制、自动驾驶、仪器和传感等方面的论文&#xff0c;当然范围不止这些&#xff0c;感兴趣的可以自行登录TIE官网查看。所投稿论文必须经过实验验证&#xff0c;偏工程应用类&#xff0c;当然也必须有方法上的…