C++二分算法:得到子序列的最少操作次数

本文涉及的基础知识点

二分查找算法合集

题目

给你一个数组 target ,包含若干 互不相同 的整数,以及另一个整数数组 arr ,arr 可能 包含重复元素。
每一次操作中,你可以在 arr 的任意位置插入任一整数。比方说,如果 arr = [1,4,1,2] ,那么你可以在中间添加 3 得到 [1,4,3,1,2] 。你可以在数组最开始或最后面添加整数。
请你返回 最少 操作次数,使得 target 成为 arr 的一个子序列。
一个数组的 子序列 指的是删除原数组的某些元素(可能一个元素都不删除),同时不改变其余元素的相对顺序得到的数组。比方说,[2,7,4] 是 [4,2,3,7,2,1,4] 的子序列(加粗元素),但 [2,4,2] 不是子序列。
示例 1:
输入:target = [5,1,3], arr = [9,4,2,3,4]
输出:2
解释:你可以添加 5 和 1 ,使得 arr 变为 [5,9,4,1,2,3,4] ,target 为 arr 的子序列。
示例 2:
输入:target = [6,4,8,1,3,2], arr = [4,7,6,2,3,8,6,1]
输出:3
参数范围
1 <= target.length, arr.length <= 105
1 <= target[i], arr[i] <= 109
target 不包含任何重复元素。

分析

时间复杂度

O(nlogn),枚举arr的时间复杂度O(n),处理arr的每个元素都需要二分查找,时间复杂度O(n)。

最长公共子序列

本题转换一下就是:求 target的长度减两者的公共最长子序列的长度。

注意

target 中没有重复的元素,所以可以将nums[i]替换成它的索引。比如: target= {3,2,1},arr={2,3}。
替换成{0,1,2},{1,0}。arr存在,但target中不存在的元素,忽略掉,比如:设置为-1,处理的时候忽略掉。

大致步骤。

一,值变索引。

 mValueIndex[target[i]] = i;

二,依次枚举arr[i]。

for (const auto& n : arr)

vLenToEndIndex

vLenToEndIndex见的淘汰

vLenToEndIndex[i]如果有多个值,淘汰值大的。因为索引越小越容易组成新的子序列。

含义

vLenToEndIndex[i]为j,表示目前长度为i+1的子序列的末尾元素的值(同时也是target中的索引)是j。
构建以n结果的公共子序列的两者方法:

只有n一个元素的子序列
如果存在j<n,且以j结尾的公共序列此系列+i

令n在 arr中的索引为i,则除掉被淘汰的公共子序列,以arr[0,i)结尾的公共子序列都在vLenToEndIndex中。vLenToEndIndex[j]小于n,说明vLenToEndIndex[j]在target的位置在n之前。也就是此子系列的结尾元素在target和arr中,都在n之前,故可以组成新的子序列。如果有多个vLenToEndIndex[j]符合条件取最大j。j+1就是新系列的长度。

vLenToEndIndex是严格递增

一,初始状态下,空向量符合严格递增。
二,如果vLenToEndIndex所有元素小于n,则n追加到最后,显然是严格递增。
三,it是第一个大于等于n的数。也就是a,it之前的数都小于n。b,由于vLenToEndIndex是严格递增,所有it后面的数大于it,而it>=n,故后面的元素>n。所以以下代码不会影响严格递增。

*it = n;

代码

核心代码

class Solution {
public:
int minOperations(vector& target, vector& arr) {
unordered_map<int, int> mValueIndex;
for (int i = 0; i < target.size(); i++)
{
mValueIndex[target[i]] = i;
}
for (auto& n : arr)
{
if (mValueIndex.count(n))
{
n = mValueIndex[n];
}
else
{
n = -1;
}
}
vector vLenToEndIndex;
for (const auto& n : arr)
{
if (-1 == n)
{
continue;
}
auto it = std::lower_bound(vLenToEndIndex.begin(), vLenToEndIndex.end(), n);
if (vLenToEndIndex.end() == it)
{
vLenToEndIndex.emplace_back(n);
}
else
{
if (n < *it)
{
*it = n;
}
}
}
return target.size() - vLenToEndIndex.size();
}
};

优化后的代码

直接将符合的arr[i]复制到新数组中。

class Solution {
public:int minOperations(vector<int>& target, const vector<int>& arr) {unordered_map<int, int> mValueIndex;for (int i = 0; i < target.size(); i++){mValueIndex[target[i]] = i;}vector<int> vNew;for (auto& n : arr){if (mValueIndex.count(n)){vNew.emplace_back(mValueIndex[n]);}}vector<int> vLenToEndIndex;for (const auto& n : vNew){auto it = std::lower_bound(vLenToEndIndex.begin(), vLenToEndIndex.end(), n);if (vLenToEndIndex.end() == it){vLenToEndIndex.emplace_back(n);}else{if (n < *it){*it = n;}}}return target.size() - vLenToEndIndex.size();}
};

测试用例

template
void Assert(const T& t1, const T& t2)
{
assert(t1 == t2);
}

template
void Assert(const vector& v1, const vector& v2)
{
if (v1.size() != v2.size())
{
assert(false);
return;
}
for (int i = 0; i < v1.size(); i++)
{
Assert(v1[i], v2[i]);
}
}

int main()
{
vector target, arr;

int res;
{Solution slu;target = { 5, 1, 3 }, arr = { 9, 4, 2, 3, 4 };res = slu.minOperations(target, arr);Assert(2, res);
}
{Solution slu;target = { 6,4,8,1,3,2 }, arr = { 4,7,6,2,3,8,6,1 };res = slu.minOperations(target, arr);Assert(3, res);
}//CConsole::Out(res);

}

2023年3月旧版

class Solution {
public:
int minOperations(vector& target, vector& arr) {
std::unordered_map<int, int> mValueToIndex;
for (int i = 0; i < target.size(); i++)
{
mValueToIndex[target[i]] = i+1;
}
for (const auto& a : arr)
{
if (mValueToIndex.count(a))
{
m_arr.push_back(mValueToIndex[a]);
}
}
Do();
return target.size() - m_iMaxPublicNum;
}
void Do()
{
std::map<int, int> mValueNum;
for (const auto& a : m_arr)
{
auto it = mValueNum.lower_bound(a);
int iNum = 1;
if (mValueNum.begin() != it)
{
auto tmp = it;
iNum = (–tmp)->second + 1;
}
if (mValueNum.end() != it)
{
if (iNum >= it->second)
{
mValueNum.erase(it);
}
}
m_iMaxPublicNum = max(m_iMaxPublicNum, iNum);
mValueNum[a] = iNum;
}
}
vector m_arr;
int m_iMaxPublicNum=0;//最大公共系列
};

扩展阅读

视频课程

有效学习:明确的目标 及时的反馈 拉伸区(难度合适),可以先学简单的课程,请移步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

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

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

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

相关文章

【如何学习Python自动化测试】—— 多层窗口定位

6 、 多层窗口定位 多层窗口指的是在操作系统图形界面中&#xff0c;一个窗口被另一个窗口覆盖的情况。在多层窗口中&#xff0c;如何定位需要操作的窗口&#xff1f; 一种常见的方法是使用操作系统提供的AltTab快捷键&#xff0c;可以在打开的所有窗口中快速切换焦点。如果需要…

第十三章 控制值的转换 - 处理UTC时区指示符

文章目录 第十三章 控制值的转换 - 处理UTC时区指示符 第十三章 控制值的转换 - 处理UTC时区指示符 对于支持XML的类&#xff0c;可以指定在从XML文档导入时是否使用UTC时区指示符。同样&#xff0c;可以指定是否在导出时包含UTC时区指示符。 为此&#xff0c;指定XMLTIMEZON…

GEE生物量碳储量——利用sens和MK检验方法计算1987-2022年森林地上生物量AGB和碳储量的时空变化特征

简介: 本文是将之前已经处理好的森林生物量和碳储量数据保存到GEE Assets中,然后分别将单张影像导入到代码编辑器中,构建一个时间序列集合,并且这里需要用到的是我们给影像添加指定的时间属性,这样方便进行下一步的时序分析和空间预测。 首先,需要收集1987年至2022年期…

C语言实现Linux下TCP Server测试工具

Linux TCP Server测试工具代码 实现了接受数据并输出文本和十六制字符串 #include <stdio.h> #include<string.h> #include <unistd.h> #include <stdlib.h> #include <errno.h> #include <signal.h> #include <arpa/inet.h> #incl…

STM32内存介绍

ROM是一种只读存储器&#xff0c;经历了从NOR Flash到NAND Flash再到现在的eMMC的发展。为了便于使用和大批量生产&#xff0c;ROM进一步分为了4种类型&#xff1a;PROM、EPROM、EEPROM和Flash。PROM只能被编程一次&#xff0c;EPROM可擦写可编程且可达1000次&#xff0c;EEPRO…

leetcode/hot100

文章目录 一、哈希1.两数之和2.字母异位词分组3.最长连续序列 二、双指针4. 移动零5.盛最多水的容器6.三数之和7.接雨水 三、滑动窗口8.无重复字符的最长子串9.找到字符串中所有字母异位词 四、子串10.和为 K 的子数组 一、哈希 1.两数之和 1. 两数之和 class Solution { pu…

规则引擎Drools使用,0基础入门规则引擎Drools(二)高级语法

文章目录 系列文章索引五、规则属性1、enabled属性2、dialect属性3、salience属性4、no-loop属性5、activation-group属性6、agenda-group属性7、auto-focus属性8、timer属性9、date-effective属性10、date-expires属性 六、Drools高级语法1、global全局变量2、query查询3、fun…

20231122给RK3399的挖掘机开发板适配Android12

20231122给RK3399的挖掘机开发板适配Android12 2023/11/22 9:30 主要步骤&#xff1a; rootrootrootroot-X99-Turbo:~$ tar --use-compress-programpigz -xvpf rk356x_android12_220722.tgz rootrootrootroot-X99-Turbo:~$ cd rk_android12_220722/ rootrootrootroot-X99-Tur…

rk3568 适配以太网(mac 2 mac)

rk3568 适配以太网(mac 2 mac) MDI(Media Dependent Interface)是以太网中的一种接口标准,用于连接物理层(PHY)和数据链路层(MAC)之间的传输介质。 在以太网中,MDI通常通过RJ-45插座来实现,用于连接网线和网络设备。MDI接口提供了电气和机械特性,使得PHY和MAC能够正…

Python通过串口收发文件

单位内外网是隔离的,USB对拷线被禁用,安全优盘使用太费事,就想到了通过串口传输文件. import serial from xmodem import XMODEM import osdef Send_File(filepath, portCOM8, baudrate115200):bn os.path.basename(filepath)filesize os.stat(filepath).st_sizestrSendFile…

带记忆的超级GPT智能体,能做饭、煮咖啡、整理家务!

随着AI技术的快速迭代&#xff0c;Alexa、Siri、小度、天猫精灵等语音助手得到了广泛应用。但在自然语言理解和完成复杂任务方面仍然有限。 相比文本的标准格式&#xff0c;语音充满复杂性和多样性&#xff08;例如&#xff0c;地方话&#xff09;,传统方法很难适应不同用户的…

【每日OJ —— 20.有效的括号(栈)】

每日OJ —— 20.有效的括号&#xff08;栈&#xff09; 1.题目&#xff1a;20.有效的括号&#xff08;栈&#xff09;2.方法讲解2.1.解法2.1.1.算法讲解2.1.2.代码实现2.1.3.提交通过展示 1.题目&#xff1a;20.有效的括号&#xff08;栈&#xff09; 2.方法讲解 2.1.解法 利用…

2023 年 亚太赛 APMCM (B题)国际大学生数学建模挑战赛 |数学建模完整代码+建模过程全解全析

当大家面临着复杂的数学建模问题时&#xff0c;你是否曾经感到茫然无措&#xff1f;作为2022年美国大学生数学建模比赛的O奖得主&#xff0c;我为大家提供了一套优秀的解题思路&#xff0c;让你轻松应对各种难题。 问题一&#xff1a; 建立没有作物的玻璃温室内的温度和风速分…

C语言二十四弹--喝汽水问题

C语言解决喝汽水问题 题目&#xff1a;喝汽水&#xff0c;1瓶汽水1元&#xff0c;2个空瓶可以换一瓶汽水&#xff0c;给20元&#xff0c;可以喝多少汽水&#xff1f; 方法一、逐瓶购买法 思路&#xff1a;一瓶瓶的买 当空瓶有两个时&#xff0c;汽水数加1即可。 #include &…

MacOS 成为恶意软件活动的目标

Malwarebytes 警告称&#xff0c;一个针对 Mac 操作系统 (OS) 的数据窃取程序正在通过虚假的网络浏览器更新分发给毫无戒心的目标。 Atomic Stealer&#xff0c;也称为 AMOS&#xff0c;是 Mac OS 上流行的窃取程序。 Atomic Stealer (AMOS) 恶意软件最近被发现使用“ClearFa…

ImportError: cannot import name ‘contextfilter‘ from ‘jinja2‘解决方案

大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。现为CSDN博客专家、人工智能领域优质创作者。喜欢通过博客创作的方式对所学的…

汇编-pop出栈指令

32位汇编 执行动作分为两步&#xff1a; 第一步&#xff1a;读出数据 第二步&#xff1a;改变栈地址 如果操作数是16位&#xff0c; 则ESP加2&#xff1b; 如果操作数是32位&#xff0c; 则ESP加4 espesp2 或 espesp4 格式&#xff1a;

九、sdl显示bmp图片

前言 SDL中内置加载BMP的API&#xff0c;使用起来会更加简单&#xff0c;便于初学者学习使用SDL 如果需要加载JPG、PNG等其他格式的图片&#xff0c;可以使用第三方库&#xff1a;SDL_image 测试环境&#xff1a; ffmpeg的4.3.2自行编译版本windows环境qt5.12sdl2.0.22&…

力扣第462题 最小操作次数使数组元素相等 II C++ 排序基础 附Java代码

题目 462. 最小操作次数使数组元素相等 II 中等 相关标签 数组 数学 排序 给你一个长度为 n 的整数数组 nums &#xff0c;返回使所有数组元素相等需要的最小操作数。 在一次操作中&#xff0c;你可以使数组中的一个元素加 1 或者减 1 。 示例 1&#xff1a; 输入&a…

Python深入分享之闭包

闭包(closure)是函数式编程的重要的语法结构。函数式编程是一种编程范式 (而面向过程编程和面向对象编程也都是编程范式)。在面向过程编程中&#xff0c;我们见到过函数(function)&#xff1b;在面向对象编程中&#xff0c;我们见过对象(object)。函数和对象的根本目的是以某种…