相等序列
题目链接:https://www.nowcoder.com/questionTerminal/7492dceb022a4bbebb990695c107823e
题目描述
题目给定a1,a2...an,这样一个长度为n的序列,现在你可以给其中一些元素加上一个值x(只能加一次),然后可以给另外一些值减上一个值x(只能减一次),剩下的元素不能再进行操作。问最后有没有可能找到一个值x使所有元素的值相等。
输入描述:
输入第一行为一个整数k,代表有k个序列(k<100),接下来有2*k行:
偶数行为一个整数n,代表给定序列的长度(1<=n<=100,000)
奇数行包含n个元素,a1,a2...an,代表序列中的元素(0<=ai<=100,000)
输出描述:
输出k行,每行一个YES或者NO
示例1
输入
1
5
1 3 3 2 1
输出
YES
AC代码:
#include<bits/stdc++.h> using namespace std; int main() { int k; cin>>k; while(k--) { int n; int x; cin>>n; set<int> s; for(int i=0;i<n;i++) { cin>>x; s.insert(x); } set<int>::iterator it=s.begin(); string ans; if(s.size()<3) ans="YES"; else if(s.size()==3) { if((*s.begin()+*s.rbegin())/2==*(++it)) ans="YES"; else ans="NO"; } else ans="NO"; cout<<ans<<endl; } }
更加完善的AC_codes:
#include<bits/stdc++.h> using namespace std; int main() { int k; cin>>k; while(k--) { int n; int x; cin>>n; set<int> s; for(int i=0;i<n;i++) { cin>>x; s.insert(x); } set<int>::iterator it=s.begin(); string ans; if(s.size()<3) ans="YES"; else if(s.size()==3) { if((*s.begin()+*s.rbegin())==2*(*(++it))) ans="YES"; else ans="NO"; } else ans="NO"; cout<<ans<<endl; } }
参考大佬的相关思路:
链接:https://www.nowcoder.com/questionTerminal/7492dceb022a4bbebb990695c107823e
来源:牛客网
序列的某些元素要同时增,减x之后 能够保持所有元素值一样,直接整个遍历计算是不现实的。
我们知道,每次增,减的值应当是固定的,也就是x,那就说明比如:不能拿大的减1,小的加2这种形式,要么大的都减2,小的都加2;要么大的都减1,小的都加1。那要保证某两部分,一部分加x,一部分减x,最后要达到相等,那必然存在一个中介,这个中介是不能动的。就比如1 2 3这个序列,2是不能动的,1,3做减,加操作后,要和2相等,这就是我们所熟知的等差序列性质。那推广一下,1,2和3都可能都多个,比如1 1 1 2 2 2 3 3 3这种,但是唯一不变的就是数的类型只能有3种,不能说1 2 3 4这样子,那就不可能达到相等,因为上面分析过了,只能有1个中介。
思考到这里,就基本可以确定思路了:我们不需要拿出所有的数(1 1 1 2 2 2 3 3 3),而只需要取出一个样本(1 2 3),同时样本数不能超过3个(1 2 3 4是不可以的),然后拿这3个样本来进行等差数列的分析(a[0] + a[2] = 2*a[1]),满足的话ans = “YES”,否则ans = "NO"。当然,不要忘了样本可能只有1个或者2个,那必然ans = "YES"。
而要样本数只拿出一个,当然用的就是set容器了,利用它的去重和排序,我们可以省去大笔功夫,直接进行等差序列判断
链接:https://www.nowcoder.com/questionTerminal/7492dceb022a4bbebb990695c107823e 来源:牛客网 #include <iostream> #include <set> #include <string> using namespace std; int main(){ int k; //k个序列 cin >> k; while(k--){ int n; //序列长度 int num; //元素值 cin >> n; set<int> res; //存储每一行的元素,但是每种类型只能存1个,并且会排序 for(int i = 0; i < n; ++i){ cin>>num; res.insert(num); } set<int>::iterator it = res.begin(); string ans; if(res.size() < 3){ ans = "YES"; } else if(res.size() == 3){ //只能一增一减,又因为是有序的,所以第一个增,第三个减,第二个不变。 //比如1 5 8 就是不可以的,1 5 9就是可以的,利用等差序列性质 //注意这里不能用res.end,因为end是指向最后一个元素的下一个位置 if((*res.begin() + *res.rbegin())/2 == *(++it)){ ans = "YES"; } else{ ans = "NO"; } } else{ ans = "NO"; } cout << ans << endl; } return 0; }
其他关于等差数列的小trick:
https://www.cnblogs.com/mtcnn/p/9423846.html
https://blog.csdn.net/qq_24489717/article/details/50350449