https://nanti.jisuanke.com/t/25090
蒜头君得到了 nn 个数,他想对这些数进行下面这样的操作,选出最左边的相邻的差的绝对值为 11 的两个数,只保留较小的数,删去较大的数,直到没有两个相邻的差的绝对值为 11 的数,问最多可以进行多少次这样的操作?
输入格式
输入第一行为一个整数 n(1 \leq n \leq 10^5)n(1≤n≤105),表示数字的总数
第二行为 nn 个整数 x_1,x_2,...,x_n(0 \leq x_i \leq 10^9)x1,x2,...,xn(0≤xi≤109),表示这些数。
输出格式
输出一行,为一个整数,表示蒜头君最多可以进行多少次这样的操作。
样例输入
4 1 2 0 1
样例输出
3
直接vector超时:
#include <bits/stdc++.h>
//#include <iostream>
using namespace std;
vector <int> myv;
int main(){
int n;
cin >> n;
for(int i = 0; i < n; i++){
int x;
cin >> x;
myv.push_back(x);
}
int flag = 1, ct = 0;
while(flag){
flag = 0;
for(int i = 0; i < myv.size() - 1; i++){
if(abs(myv[i] - myv[i + 1]) == 1){
flag = 1;
int min = myv[i] < myv[i + 1] ? i : i + 1;
myv.erase(myv.begin() + min);
ct++;
break;
}
}
}
cout << ct << endl;
return 0;
}
方法一:数组模拟,用一个数组存放,挨个比较放入:
#include <iostream>
using namespace std;
const int N = 1e5 + 5;
long long a[N];
int main(){
int n, x;
cin >> n;
int ct = 0;
int ans = 0;
for(int i = 0; i < n; i++){
if(i == 0){
cin >> a[i];
}
else{
cin >> x;
if(x - a[ct] == 1){
continue;
}
else if(a[ct] - x == 1){ //删除数据时往前检测
a[ct] = x;
while(1){
if(ct >= 1){
if(a[ct] - a[ct - 1] == 1){
ct--;
}
else if(a[ct - 1] - a[ct] == 1){
a[ct - 1] = a[ct];
ct--;
}
else{
break;
}
}
else{
break;
}
}
}
else{
ct++;
a[ct] = x;
}
}
}
ans = n - (ct + 1); //减去上的个数
cout << ans << endl;
return 0;
}
/*
4
1 3 2 4
*/
方法二:链表:
list:
list <int> p;
list <int>::iterator it = p.begian();
for(it = p.begin(); it != p.end(); it++){} //p.eng()指向的是最后一个元素的下一位
p.begian();
p.end();
p.push_back();
p.push_front();
p.empty();
p.resize();
p.clear();
p.front(); //获得头部元素
p.back();
p.pop_back(); //删除第一个元素
p.pop_front();
p.reverse(); //倒置
p.insert(); //指定位置插入,括号放地址
p.erase(); //弹出指定位置的元素,注意弹出后改地址代表的元素
还是原来的值,只是和链表断开了连接,不能再通过it--或it++
在获得链表上的地址了,所以弹出前保持好连接,并用另一个变量去弹
掉。
#include <iostream>
#include <cmath>
#include <list>
using namespace std;
list <int> my1;
int main(){
std::ios::sync_with_stdio(false);
int n, x;
cin >> n;
for(int i = 0; i < n; i++){
cin >> x;
my1.push_back(x);
}
list <int>::iterator it;
list <int>::iterator tt;
for(list <int>::iterator it = my1.begin(); it != my1.end() && my1.size() >= 2; ){
++it;
tt = it;
tt--; //it前一个
if(*it - *tt == 1){
list <int>::iterator p = it;
it++;
my1.erase(p); //注意 p 弹出来之后就从链表没有关联了,所以要用一个临时变量去搞,并在那个地址失效前让it改变到下一个
}
else if(*tt - *it == 1){ //请一个弹出来后,要往前检测更新前面的
list <int>::iterator p = tt;
tt--;
my1.erase(p);
while(abs(*tt - *it) == 1){
if(*it - *tt == 1){
list <int>::iterator p = it;
it++;
my1.erase(p);
}
else if(*tt - *it == 1){
list <int>::iterator p = tt;
tt--;
my1.erase(p);
}
}
}
}
cout << n - my1.size() << endl;
return 0;
}
方法三:用栈感觉是最优的;
#include <iostream>
#include <cmath>
#include <stack>
using namespace std;
stack <int> p;
int main(){
std::ios::sync_with_stdio(false);
int n, x, flag = 1;
cin >> n;
for(int i = 0; i < n; i++){
cin >> x;
flag = 1;
while(!p.empty() && abs(p.top() - x) == 1){
if(x - p.top() == 1){
flag = 0;
break;
}
else{
p.pop();
}
}
if(flag){
p.push(x);
}
}
cout << n - p.size() << endl;
return 0;
}
浙公网安备 33010602011771号