70-合并数字

https://nanti.jisuanke.com/t/25090

  •  14.25%
  •  1000ms
  •  262144K
 

蒜头君得到了 nn 个数,他想对这些数进行下面这样的操作,选出最左边的相邻的差的绝对值为 11 的两个数,只保留较小的数,删去较大的数,直到没有两个相邻的差的绝对值为 11 的数,问最多可以进行多少次这样的操作?

输入格式

输入第一行为一个整数 n(1 leq n leq 10^5)n(1n105),表示数字的总数

第二行为 nn 个整数 x_1,x_2,...,x_n(0 leq x_i leq 10^9)x1,x2,...,xn(0xi109),表示这些数。

输出格式

输出一行,为一个整数,表示蒜头君最多可以进行多少次这样的操作。

样例输入

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

  

原文地址:https://www.cnblogs.com/zhumengdexiaobai/p/8653903.html