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; }