497.队列 难度:中
注:本题所使用的解题语言为c++,所使用到的库为:vector 、iostream
题目展示
给定一个长度为 的序列 ,你可以选择删去其中最多 个数,得到一个新序列 (),新序列保留原来的相对顺序。你的目标是删除某些数,使得新序列的第 个数 。现在需要求出最少删除多少个数才能得到这样的序列,如果无法得到,输出 。
例如,对于序列 [1, 4, 2, 3, 5],删除第 2 个和第 5 个元素后,可以得到序列 [1, 2, 3]。
测试样例
样例1:
输入:
n = 5 ,a = [1, 4, 2, 3, 5]输出:2
样例2:
输入:
n = 3 ,a = [3, 3, 2]输出:-1
样例3:
输入:
n = 5 ,a = [1, 2, 3, 4, 5]输出:0
相关知识点
1、vector中如何按照位置删除元素
实际上,我们在翻阅了对应的的c++手册,以及对应查找相关的资料之后,我们便可以发现,在c++
vector数据类型当中,有这样一个方法:std::vector::erase这样一个方法,这个方法本质上是删除在对应的vector中的所有的元素,但如果其方法参数内包含pos参数时,那么这个方法会特定的指向对应的位置,进而删除这个位置上特定的元素(但是需要注意的一点是,这个pos参数实际上为auto 类型,需要再定义对应的auto变量从而能定位到对应的元素中去)
2、auto类型的简单介绍
对于auto类型,在互联网的资料当中,它是被这么定义的: auto是一个C/C++语言存储类型,仅在语句块内部使用,初始化可为任何表达式,其特点是当执行流程进入该语句块的时候初始化可为任何表达式。实际上简单来说就好像一颗能自动变换的“螺丝钉”,根据不同的代码自动变换为不同的形式,而这实际上也正好在各种各样的方法中提供对应的位置显示和提示
代码思路解析
实际上,为了写出这道题目,我们先要对题目的要求进行分析,题目所要求的是最少删除多少个数才能得到这样的序列,如果无法输出,则得到-1,那么我们可以对所使用的数据结构进行分析,在所使用的数据结构中,我们可以发现所使用的为Vector容器,而vector容器在另一种角度上就相当于可扩容的数组,而我们便可以利用这一特性对于vector做循环,如果vector中的某一个值超出题目所给定的范围或不等于对应的索引,就剔除该元素,如果符合题目要求,就跳过,知道数组遍历完毕,并且如果数组不符合要求,其内部的所有元素也会被剔除,对应数组内没有元素,而这样我们便可以对应的判定数组是否成立,从而达到题目要求
注意事项
1、在erase这个方法中,为了清除对应位置的元素,我们需要定义一个auto变量,那么这个auto变量我们就可以使用 arr.begin()+i从而定位到相关的方法 注:arr为数组名,i为对应的位置
2、为了使得循环只遍历一遍,我们其实在for循环的定义时设置只在符合要求的i时,i进行增加,反之直接进行擦除对应的元素,这样可以使得一遍循环就可以得到对应的元素。
而在前期对于代码进行分析和书写之后,我们便可以书写详细的代码如下:
详细代码
#include <iostream>
#include <vector>
using namespace std;
int solution(int n, vector<int>& a) {
// 用于记录每个位置上的数是否符合要求
int count = 0;
int capacity = n;
// 遍历数组,记录每个数是否在正确的位置上
for (int i = 0; i < capacity;) {
if (a[i] == i + 1) {
i++;
continue;
}
else {
auto er = a.begin()+i;
a.erase(er);
count++;
capacity--;
i = 0;
}
}
if(capacity==0){
return -1;
}
return count;
}
int main() {
vector<int> v1 = {1, 4, 2, 3, 5};
vector<int> v2 = {3, 3, 2};
vector<int> v3 = {1, 2, 3, 4, 5};
cout << (solution(3, v2) == -1) << endl;
cout << (solution(5, v3) == 0) << endl;
return 0;
}