C++单调向量算法:得到山形数组的最少删除次数

2023-11-23 07:36

本文主要是介绍C++单调向量算法:得到山形数组的最少删除次数,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

本题的其它解法

C++二分算法:得到山形数组的最少删除次数

题目

我们定义 arr 是 山形数组 当且仅当它满足:
arr.length >= 3
存在某个下标 i (从 0 开始) 满足 0 < i < arr.length - 1 且:
arr[0] < arr[1] < … < arr[i - 1] < arr[i]
arr[i] > arr[i + 1] > … > arr[arr.length - 1]
给你整数数组 nums​ ,请你返回将 nums 变成 山形状数组 的​ 最少 删除次数。
示例 1:
输入:nums = [1,3,1]
输出:0
解释:数组本身就是山形数组,所以我们不需要删除任何元素。
示例 2:
输入:nums = [2,1,1,5,6,2,3,1]
输出:3
解释:一种方法是将下标为 0,1 和 5 的元素删除,剩余元素为 [1,5,6,3,1] ,是山形数组。
参数范围
3 <= nums.length <= 1000
1 <= nums[i] <= 109
题目保证 nums 删除一些元素后一定能得到山形数组。

分析

本题可以转换成:最长山形数组,再进一步转换成最长升序子序列。

时间复杂度

时间复杂度O(nlogn)。分两步:一,寻找左半部分。二,寻找右半部分。每步枚举每个山顶,时间复杂度O(n),每个山顶二分查找一次,时间复杂度O(logn)。

vLenToMin

vLenToMin[i]的含义是 长度为i+1 的子序列 的结尾,如果有多个符合的子序列,取结尾最小的。
比如:

原始数组vLenToMin
11
1 2{1}->{1,2}
2 1{2}->{1}
1 2 3{1}->{1,2
1 3 3 4 5{1}->{1,3}->{1,3,4}->{1,3,4,5}
1 3 5 4{1}->{1,3}->{1,3,5}->{1,3,4}

总结

一,只会在尾部增加元素。不会在其它位置增加元素。
二,不会删除元素。
三,会替换元素。
四,严格递增。
五,所有的数都小于当前值时,在末尾增加,显然是升序。
六,it第一个大于等于n的迭代器,之前的元素一定严格小于it,而it<=n,故前面元素一定小于n。
后面的元素不会ij等于it,否则它就是*it。[ii,…)都大于等于n,所有ij不会小于n。
七,规则五和六保证了vLenToMin永远严格递增。

代码

核心代码

class Solution {
public:int minimumMountainRemovals(vector<int>& nums) {vector<int> vLeftLen,vRightLen;Do(vLeftLen, nums);Do(vRightLen, vector<int>(nums.rbegin(), nums.rend()));std::reverse(vRightLen.begin(), vRightLen.end());int iMaxLen = 0;for (int i = 1; i+1 < nums.size(); i++){if ((vLeftLen[i] > 1) && (vRightLen[i] > 1)){iMaxLen = max(iMaxLen, vLeftLen[i] + vRightLen[i] - 1);}}return nums.size() - iMaxLen;}void Do(vector<int>& vLen, const vector<int> nums){vector<int> vLenToMin;//vLenToMin[i]的含义是 长度为i+1 的子序列 的结尾,如果有多个符合的子序列,取结尾最小的。for (const auto& n : nums){auto it = std::lower_bound(vLenToMin.begin(), vLenToMin.end(), n);vLen.emplace_back(it - vLenToMin.begin() + 1);if (vLenToMin.end() == it){vLenToMin.emplace_back(n);}else{if (n < *it){*it = n;}}}}
};

测试用例

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 nums;
int res;
{
Solution slu;
nums = { 1,3,1 };
res = slu.minimumMountainRemovals(nums);
Assert(0, res);
}
{
Solution slu;
nums = { 2, 1, 1, 5, 6, 2, 3, 1 };
res = slu.minimumMountainRemovals(nums);
Assert(3, res);
}
{
Solution slu;
nums = { 9, 8, 1, 7, 6, 5, 4, 3, 2, 1 };
res = slu.minimumMountainRemovals(nums);
Assert(2, res);
}
{
Solution slu;
nums = { 100, 92, 89, 77, 74, 66, 64, 66, 64 };
res = slu.minimumMountainRemovals(nums);
Assert(6, res);
}
{
Solution slu;
nums = { 1, 2, 1, 3, 4, 4 };
res = slu.minimumMountainRemovals(nums);
Assert(3, res);
}

//CConsole::Out(res);

}

扩展阅读

视频课程

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

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

这篇关于C++单调向量算法:得到山形数组的最少删除次数的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/416358

相关文章

Mysql实现范围分区表(新增、删除、重组、查看)

《Mysql实现范围分区表(新增、删除、重组、查看)》MySQL分区表的四种类型(范围、哈希、列表、键值),主要介绍了范围分区的创建、查询、添加、删除及重组织操作,具有一定的参考价值,感兴趣的可以了解... 目录一、mysql分区表分类二、范围分区(Range Partitioning1、新建分区表:2、分

MySQL 删除数据详解(最新整理)

《MySQL删除数据详解(最新整理)》:本文主要介绍MySQL删除数据的相关知识,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录一、前言二、mysql 中的三种删除方式1.DELETE语句✅ 基本语法: 示例:2.TRUNCATE语句✅ 基本语

MySQL查询JSON数组字段包含特定字符串的方法

《MySQL查询JSON数组字段包含特定字符串的方法》在MySQL数据库中,当某个字段存储的是JSON数组,需要查询数组中包含特定字符串的记录时传统的LIKE语句无法直接使用,下面小编就为大家介绍两种... 目录问题背景解决方案对比1. 精确匹配方案(推荐)2. 模糊匹配方案参数化查询示例使用场景建议性能优

关于集合与数组转换实现方法

《关于集合与数组转换实现方法》:本文主要介绍关于集合与数组转换实现方法,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1、Arrays.asList()1.1、方法作用1.2、内部实现1.3、修改元素的影响1.4、注意事项2、list.toArray()2.1、方

Java中的雪花算法Snowflake解析与实践技巧

《Java中的雪花算法Snowflake解析与实践技巧》本文解析了雪花算法的原理、Java实现及生产实践,涵盖ID结构、位运算技巧、时钟回拨处理、WorkerId分配等关键点,并探讨了百度UidGen... 目录一、雪花算法核心原理1.1 算法起源1.2 ID结构详解1.3 核心特性二、Java实现解析2.

从入门到精通C++11 <chrono> 库特性

《从入门到精通C++11<chrono>库特性》chrono库是C++11中一个非常强大和实用的库,它为时间处理提供了丰富的功能和类型安全的接口,通过本文的介绍,我们了解了chrono库的基本概念... 目录一、引言1.1 为什么需要<chrono>库1.2<chrono>库的基本概念二、时间段(Durat

C++20管道运算符的实现示例

《C++20管道运算符的实现示例》本文简要介绍C++20管道运算符的使用与实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧... 目录标准库的管道运算符使用自己实现类似的管道运算符我们不打算介绍太多,因为它实际属于c++20最为重要的

一文详解Git中分支本地和远程删除的方法

《一文详解Git中分支本地和远程删除的方法》在使用Git进行版本控制的过程中,我们会创建多个分支来进行不同功能的开发,这就容易涉及到如何正确地删除本地分支和远程分支,下面我们就来看看相关的实现方法吧... 目录技术背景实现步骤删除本地分支删除远程www.chinasem.cn分支同步删除信息到其他机器示例步骤

Visual Studio 2022 编译C++20代码的图文步骤

《VisualStudio2022编译C++20代码的图文步骤》在VisualStudio中启用C++20import功能,需设置语言标准为ISOC++20,开启扫描源查找模块依赖及实验性标... 默认创建Visual Studio桌面控制台项目代码包含C++20的import方法。右键项目的属性:

python删除xml中的w:ascii属性的步骤

《python删除xml中的w:ascii属性的步骤》使用xml.etree.ElementTree删除WordXML中w:ascii属性,需注册命名空间并定位rFonts元素,通过del操作删除属... 可以使用python的XML.etree.ElementTree模块通过以下步骤删除XML中的w:as